diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	2004-07-15 10:11:18 -07:00
+++ b/CREDITS	2004-08-27 18:55:19 -07:00
@@ -735,6 +735,12 @@
 S: D-69231 Rauenberg
 S: Germany
 
+N: Jean Delvare
+E: khali@linux-fr.org
+W: http://khali.linux-fr.org/
+D: Several hardware monitoring drivers
+S: France
+
 N: Peter Denison
 E: peterd@pnd-pc.demon.co.uk
 W: http://www.pnd-pc.demon.co.uk/promise/
@@ -754,7 +760,7 @@
 D: HTB qdisc and random networking hacks
 
 N: Alex deVries
-E: adevries@thepuffingroup.com
+E: alex@onefishtwo.ca
 D: Various SGI parts, bits of HAL2 and Newport, PA-RISC Linux.
 S: 41.5 William Street
 S: Ottawa, Ontario
@@ -2214,14 +2220,13 @@
 S: Netherlands
 
 N: David S. Miller
-E: davem@redhat.com
+E: davem@davemloft.net
 D: Sparc and blue box hacker
 D: Vger Linux mailing list co-maintainer
 D: Linux Emacs elf/qmagic support + other libc/gcc things
 D: Yee bore de yee bore! ;-)
-S: 750 N. Shoreline Blvd.
-S: Apt. #111
-S: Mountain View, California 94043
+S: 575 Harrison St. #103
+S: San Francisco, CA 94105
 S: USA
 
 N: Rick Miller
@@ -2837,6 +2842,9 @@
 S: Markusstrasse 18
 S: 8006 Zuerich
 S: Switzerland
+
+N: Manuel Estrada Sainz
+D: Firmware loader (request_firmware)
 
 N: Wayne Salamon
 E: wsalamon@tislabs.com
diff -Nru a/Documentation/CodingStyle b/Documentation/CodingStyle
--- a/Documentation/CodingStyle	2004-04-12 10:54:23 -07:00
+++ b/Documentation/CodingStyle	2004-08-24 11:41:29 -07:00
@@ -356,10 +356,10 @@
 
 Macros with multiple statements should be enclosed in a do - while block:
 
-#define macrofun(a,b,c) 			\
+#define macrofun(a, b, c) 			\
 	do {					\
 		if (a == 5)			\
-			do_this(b,c);		\
+			do_this(b, c);		\
 	} while (0)
 
 Things to avoid when using macros:
diff -Nru a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
--- a/Documentation/DMA-API.txt	2004-06-29 07:44:49 -07:00
+++ b/Documentation/DMA-API.txt	2004-06-30 19:01:43 -07:00
@@ -444,4 +444,83 @@
 continuing on for size.  Again, you *must* observe the cache line
 boundaries when doing this.
 
+int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+			    dma_addr_t device_addr, size_t size, int
+			    flags)
+
+
+Declare region of memory to be handed out by dma_alloc_coherent when
+it's asked for coherent memory for this device.
+
+bus_addr is the physical address to which the memory is currently
+assigned in the bus responding region (this will be used by the
+platform to perform the mapping)
+
+device_addr is the physical address the device needs to be programmed
+with actually to address this memory (this will be handed out as the
+dma_addr_t in dma_alloc_coherent())
+
+size is the size of the area (must be multiples of PAGE_SIZE).
+
+flags can be or'd together and are
+
+DMA_MEMORY_MAP - request that the memory returned from
+dma_alloc_coherent() be directly writeable.
+
+DMA_MEMORY_IO - request that the memory returned from
+dma_alloc_coherent() be addressable using read/write/memcpy_toio etc.
+
+One or both of these flags must be present
+
+DMA_MEMORY_INCLUDES_CHILDREN - make the declared memory be allocated by
+dma_alloc_coherent of any child devices of this one (for memory residing
+on a bridge).
+
+DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions. 
+Do not allow dma_alloc_coherent() to fall back to system memory when
+it's out of memory in the declared region.
+
+The return value will be either DMA_MEMORY_MAP or DMA_MEMORY_IO and
+must correspond to a passed in flag (i.e. no returning DMA_MEMORY_IO
+if only DMA_MEMORY_MAP were passed in) for success or zero for
+failure.
+
+Note, for DMA_MEMORY_IO returns, all subsequent memory returned by
+dma_alloc_coherent() may no longer be accessed directly, but instead
+must be accessed using the correct bus functions.  If your driver
+isn't prepared to handle this contingency, it should not specify
+DMA_MEMORY_IO in the input flags.
+
+As a simplification for the platforms, only *one* such region of
+memory may be declared per device.
+
+For reasons of efficiency, most platforms choose to track the declared
+region only at the granularity of a page.  For smaller allocations,
+you should use the dma_pool() API.
+
+void
+dma_release_declared_memory(struct device *dev)
+
+Remove the memory region previously declared from the system.  This
+API performs *no* in-use checking for this region and will return
+unconditionally having removed all the required structures.  It is the
+drivers job to ensure that no parts of this memory region are
+currently in use.
+
+void *
+dma_mark_declared_memory_occupied(struct device *dev,
+				  dma_addr_t device_addr, size_t size)
+
+This is used to occupy specific regions of the declared space
+(dma_alloc_coherent() will hand out the first free region it finds).
+
+device_addr is the *device* address of the region requested
+
+size is the size (and should be a page sized multiple).
+
+The return value will be either a pointer to the processor virtual
+address of the memory, or an error (via PTR_ERR()) if any part of the
+region is occupied.
+
 
diff -Nru a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
--- a/Documentation/DocBook/gadget.tmpl	2004-02-24 00:18:48 -08:00
+++ b/Documentation/DocBook/gadget.tmpl	2004-08-21 17:34:24 -07:00
@@ -2,8 +2,8 @@
 <book id="USB-Gadget-API">
   <bookinfo>
     <title>USB Gadget API for Linux</title>
-    <date>02 June 2003</date>
-    <edition>02 June 2003</edition>
+    <date>20 August 2004</date>
+    <edition>20 August 2004</edition>
   
     <legalnotice>
        <para>
@@ -34,7 +34,7 @@
        </para>
     </legalnotice>
     <copyright>
-      <year>2003</year>
+      <year>2003-2004</year>
       <holder>David Brownell</holder>
     </copyright>
 
@@ -73,9 +73,13 @@
 	composite devices,
 	and alternate interface settings.
 	</para></listitem>
+    <listitem><para>USB "On-The-Go" (OTG) support, in conjunction
+	with updates to the Linux-USB host side.
+	</para></listitem>
     <listitem><para>Sharing data structures and API models with the
-	Linux-USB host side API.  This looks forward to USB "On-The-Go"
-	(OTG) and similar more-symmetric frameworks.
+	Linux-USB host side API.  This helps the OTG support, and
+	looks forward to more-symmetric frameworks (where the same
+	I/O model is used by both host and device side drivers).
 	</para></listitem>
     <listitem><para>Minimalist, so it's easier to support new device
 	controller hardware.  I/O processing doesn't imply large
@@ -153,6 +157,7 @@
 	the SA-11x0 or PXA-25x UDC (found within many PDAs),
 	and a variety of other products.
 	</para>
+
 	</listitem></varlistentry>
 
     <varlistentry>
@@ -162,10 +167,14 @@
 	<para>The lower boundary of this driver implements hardware-neutral
 	USB functions, using calls to the controller driver.
 	Because such hardware varies widely in capabilities and restrictions,
-	the gadget driver is normally configured at compile time
+	and is used in embedded environments where space is at a premium,
+	the gadget driver is often configured at compile time
 	to work with endpoints supported by one particular controller.
 	Gadget drivers may be portable to several different controllers,
 	using conditional compilation.
+	(Recent kernels substantially simplify the work involved in
+	supporting new hardware, by <emphasis>autoconfiguring</emphasis>
+	endpoints automatically for many bulk-oriented drivers.)
 	Gadget driver responsibilities include:
 	</para>
 	<itemizedlist>
@@ -178,8 +187,9 @@
 		altsettings, including enabling and configuring endpoints
 		</para></listitem>
 	    <listitem><para>handling life cycle events, such as managing
-		bindings
-	        to hardware, and disconnection from the USB host.
+		bindings to hardware,
+		USB suspend/resume, remote wakeup,
+		and disconnection from the USB host.
 		</para></listitem>
 	    <listitem><para>managing IN and OUT transfers on all currently
 		enabled endpoints
@@ -244,15 +254,38 @@
 
 </variablelist>
 
-<para>Over time, reusable utilities should evolve to help make some
-gadget driver tasks simpler.  An example of particular interest
+<para>OTG-capable systems will also need to include a standard Linux-USB
+host side stack,
+with <emphasis>usbcore</emphasis>,
+one or more <emphasis>Host Controller Drivers</emphasis> (HCDs),
+<emphasis>USB Device Drivers</emphasis> to support
+the OTG "Targeted Peripheral List",
+and so forth.
+There will also be an <emphasis>OTG Controller Driver</emphasis>,
+which is visible to gadget and device driver developers only indirectly.
+That helps the host and device side USB controllers implement the
+two new OTG protocols (HNP and SRP).
+Roles switch (host to peripheral, or vice versa) using HNP
+during USB suspend processing, and SRP can be viewed as a
+more battery-friendly kind of device wakeup protocol.
+</para>
+
+<para>Over time, reusable utilities are evolving to help make some
+gadget driver tasks simpler.
+For example, building configuration descriptors from vectors of
+descriptors for the configurations interfaces and endpoints is
+now automated, and many drivers now use autoconfiguration to
+choose hardware endpoints and initialize their descriptors.
+
+A potential example of particular interest
 is code implementing standard USB-IF protocols for
 HID, networking, storage, or audio classes.
 Some developers are interested in KDB or KGDB hooks, to let
 target hardware be remotely debugged.
 Most such USB protocol code doesn't need to be hardware-specific,
 any more than network protocols like X11, HTTP, or NFS are.
-Such interface drivers might be combined, to support composite devices.
+Such gadget-side interface drivers should eventually be combined,
+to implement composite devices.
 </para>
 
 </chapter>
@@ -284,7 +317,7 @@
 <para>However, docproc does not understand all the C constructs
 that are used, so some relevant information is likely omitted from
 what you are reading.  
-One example of such information is several per-request flags.
+One example of such information is endpoint autoconfiguration.
 You'll have to read the header file, and use example source
 code (such as that for "Gadget Zero"), to fully understand the API.
 </para>
@@ -292,7 +325,7 @@
 <para>The part of the API implementing some basic
 driver capabilities is specific to the version of the
 Linux kernel that's in use.
-The 2.5 kernel includes a <emphasis>driver model</emphasis>
+The 2.6 kernel includes a <emphasis>driver model</emphasis>
 framework that has no analogue on earlier kernels;
 so those parts of the gadget API are not fully portable.
 (They are implemented on 2.4 kernels, but in a different way.)
@@ -308,17 +341,21 @@
 that would be added using hardware-specific APIs.
 </para>
 
-<para>This API expects drivers to use conditional compilation to handle
-endpoint capabilities of different hardware.
-Those tend to have arbitrary restrictions, relating to
+<para>This API allows drivers to use conditional compilation to handle
+endpoint capabilities of different hardware, but doesn't require that.
+Hardware tends to have arbitrary restrictions, relating to
 transfer types, addressing, packet sizes, buffering, and availability.
 As a rule, such differences only matter for "endpoint zero" logic
 that handles device configuration and management.
-The API only supports limited run-time
+The API supports limited run-time
 detection of capabilities, through naming conventions for endpoints.
-Although a gadget driver could scan the endpoints available to it and
-choose to map those capabilities onto driver functionality in some way,
-few drivers will want to reconfigure themselves at run-time.
+Many drivers will be able to at least partially autoconfigure
+themselves.
+In particular, driver init sections will often have endpoint
+autoconfiguration logic that scans the hardware's list of endpoints
+to find ones matching the driver requirements
+(relying on those conventions), to eliminate some of the most
+common reasons for conditional compilation.
 </para>
 
 <para>Like the Linux-USB host side API, this API exposes
@@ -355,10 +392,14 @@
 At this point the device is logically in the USB ch9 initial state
 ("attached"), drawing no power and not usable
 (since it does not yet support enumeration).
+Any host should not see the device, since it's not
+activated the data line pullup used by the host to
+detect a device, even if VBUS power is available.
 </para></listitem>
 
 <listitem><para>Register a gadget driver that implements some higher level
-device function.  That will then bind() to a usb_gadget.
+device function.  That will then bind() to a usb_gadget, which
+activates the data line pullup sometime after detecting VBUS.
 </para></listitem>
 
 <listitem><para>The hardware driver can now start enumerating.
@@ -373,6 +414,8 @@
 functionality being implemented.
 That can involve alternate settings or configurations,
 unless the hardware prevents such operation.
+For OTG devices, each configuration descriptor includes
+an OTG descriptor.
 </para></listitem>
 
 <listitem><para>The gadget driver handles the last step of enumeration,
@@ -381,13 +424,18 @@
 with all interfaces in their default settings.
 That involves using a list of the hardware's endpoints, enabling each
 endpoint according to its descriptor.
+It may also involve using <function>usb_gadget_vbus_draw</function>
+to let more power be drawn from VBUS, as allowed by that configuration.
+For OTG devices, setting a configuration may also involve reporting
+HNP capabilities through a user interface.
 </para></listitem>
 
 <listitem><para>Do real work and perform data transfers, possibly involving
 changes to interface settings or switching to new configurations, until the
 device is disconnect()ed from the host.
 Queue any number of transfer requests to each endpoint.
-The drivers then go back to step 3 (above).
+It may be suspended and resumed several times before being disconnected.
+On disconnect, the drivers go back to step 3 (above).
 </para></listitem>
 
 <listitem><para>When the gadget driver module is being unloaded,
@@ -399,7 +447,9 @@
 
 <para>Drivers will normally be arranged so that just loading the
 gadget driver module (or statically linking it into a Linux kernel)
-allows the peripheral device to be enumerated.
+allows the peripheral device to be enumerated, but some drivers
+will defer enumeration until some higher level component (like
+a user mode daemon) enables it.
 Note that at this lowest level there are no policies about how
 ep0 configuration logic is implemented,
 except that it should obey USB specifications.
@@ -410,6 +460,18 @@
 be built by integrating reusable components.
 </para>
 
+<para>Note that the lifecycle above can be slightly different
+for OTG devices.
+Other than providing an additional OTG descriptor in each
+configuration, only the HNP-related differences are particularly
+visible to driver code.
+They involve reporting requirements during the SET_CONFIGURATION
+request, and the option to invoke HNP during some suspend callbacks.
+Also, SRP changes the semantics of
+<function>usb_gadget_wakeup</function>
+slightly.
+</para>
+
 </sect1>
 
 <sect1 id="ch9"><title>USB 2.0 Chapter 9 Types and Constants</title>
@@ -418,9 +480,9 @@
 rely on common USB structures and constants
 defined in the
 <filename>&lt;linux/usb_ch9.h&gt;</filename>
-header file, which is standard in Linux 2.5 kernels.
+header file, which is standard in Linux 2.6 kernels.
 These are the same types and constants used by host
-side drivers.
+side drivers (and usbcore).
 </para>
 
 !Iinclude/linux/usb_ch9.h
@@ -451,26 +513,38 @@
 
 <para>The core API is sufficient for writing a USB Gadget Driver,
 but some optional utilities are provided to simplify common tasks.
+These utilities include endpoint autoconfiguration.
 </para>
 
 !Edrivers/usb/gadget/usbstring.c
 !Edrivers/usb/gadget/config.c
+<!-- !Edrivers/usb/gadget/epautoconf.c -->
 </sect1>
 
 </chapter>
 
 <chapter id="controllers"><title>Peripheral Controller Drivers</title>
 
-<para>The first hardware supporting this API is the NetChip 2280
+<para>The first hardware supporting this API was the NetChip 2280
 controller, which supports USB 2.0 high speed and is based on PCI.
 This is the <filename>net2280</filename> driver module.
-The driver supports Linux kernel versions 2.4 and 2.5;
+The driver supports Linux kernel versions 2.4 and 2.6;
 contact NetChip Technologies for development boards and product
 information.
 </para> 
 
-<para>For users of Intel's PXA 2xx series processors,
-a <filename>pxa2xx_udc</filename> driver is available.
+<para>Other hardware working in the "gadget" framework includes:
+Intel's PXA 25x and IXP42x series processors
+(<filename>pxa2xx_udc</filename>),
+Toshiba TC86c001 "Goku-S" (<filename>goku_udc</filename>),
+Renesas SH7705/7727 (<filename>sh_udc</filename>),
+MediaQ 11xx (<filename>mq11xx_udc</filename>),
+Hynix HMS30C7202 (<filename>h7202_udc</filename>),
+National 9303/4 (<filename>n9604_udc</filename>),
+Texas Instruments OMAP (<filename>omap_udc</filename>),
+Sharp LH7A40x (<filename>lh7a40x_udc</filename>),
+and more.
+Most of those are full speed controllers.
 </para>
 
 <para>At this writing, there are people at work on drivers in
@@ -526,6 +600,15 @@
 to avoid creating problems.)
 </para>
 
+<para>Support for Microsoft's <emphasis>RNDIS</emphasis>
+protocol has been contributed by Pengutronix and Auerswald GmbH.
+This is like CDC Ethernet, but it runs on more slightly USB hardware
+(but less than the CDC subset).
+However, its main claim to fame is being able to connect directly to
+recent versions of Windows, using drivers that Microsoft bundles
+and supports, making it much simpler to network with Windows.
+</para>
+
 <para>There is also support for user mode gadget drivers,
 using <emphasis>gadgetfs</emphasis>.
 This provides a <emphasis>User Mode API</emphasis> that presents
@@ -535,6 +618,10 @@
 develop and debug user mode drivers, so that once a robust
 controller driver is available many applications for it
 won't require new kernel mode software.
+Linux 2.6 <emphasis>Async I/O (AIO)</emphasis>
+support is available, so that user mode software
+can stream data with only slightly more overhead
+than a kernel driver.
 </para>
 
 <para>There's a USB Mass Storage class driver, which provides
@@ -548,6 +635,16 @@
 to access the data from the backing store.
 </para>
 
+<para>There's a "serial line" driver, useful for TTY style
+operation over USB.
+The latest version of that driver supports CDC ACM style
+operation, like a USB modem, and so on most hardware it can
+interoperate easily with MS-Windows.
+One interesting use of that driver is in boot firmware (like a BIOS),
+which can sometimes use that model with very small systems without
+real serial lines.
+</para>
+
 <para>Support for other kinds of gadget is expected to
 be developed and contributed
 over time, as this driver framework evolves.
@@ -555,6 +652,96 @@
 
 </chapter>
 
+<chapter id="otg"><title>USB On-The-GO (OTG)</title>
+
+<para>USB OTG support on Linux 2.6 was initially developed
+by Texas Instruments for
+<ulink url="http://www.omap.com">OMAP</ulink> 16xx and 17xx
+series processors.
+Other OTG systems should work in similar ways, but the
+hardware level details could be very different.
+</para> 
+
+<para>Systems need specialized hardware support to implement OTG,
+notably including a special <emphasis>Mini-AB</emphasis> jack
+and associated transciever to support <emphasis>Dual-Role</emphasis>
+operation:
+they can act either as a host, using the standard
+Linux-USB host side driver stack,
+or as a peripheral, using this "gadget" framework.
+To do that, the system software relies on small additions
+to those programming interfaces,
+and on a new internal component (here called an "OTG Controller")
+affecting which driver stack connects to the OTG port.
+In each role, the system can re-use the existing pool of
+hardware-neutral drivers, layered on top of the controller
+driver interfaces (<emphasis>usb_bus</emphasis> or
+<emphasis>usb_gadget</emphasis>).
+Such drivers need at most minor changes, and most of the calls
+added to support OTG can also benefit non-OTG products.
+</para>
+
+<itemizedlist>
+    <listitem><para>Gadget drivers test the <emphasis>is_otg</emphasis>
+	flag, and use it to determine whether or not to include
+	an OTG descriptor in each of their configurations.
+	</para></listitem>
+    <listitem><para>Gadget drivers may need changes to support the
+	two new OTG protocols, exposed in new gadget attributes
+	such as <emphasis>b_hnp_enable</emphasis> flag.
+	HNP support should be reported through a user interface
+	(two LEDs could suffice), and is triggered in some cases
+	when the host suspends the peripheral.
+	SRP support can be user-initiated just like remote wakeup,
+	probably by pressing the same button.
+	</para></listitem>
+    <listitem><para>On the host side, USB device drivers need
+	to be taught to trigger HNP at appropriate moments, using
+	<function>usb_suspend_device()</function>.
+	That also conserves battery power, which is useful even
+	for non-OTG configurations.
+	</para></listitem>
+    <listitem><para>Also on the host side, a driver must support the
+	OTG "Targeted Peripheral List".  That's just a whitelist,
+	used to reject peripherals not supported with a given
+	Linux OTG host.
+	<emphasis>This whitelist is product-specific;
+	each product must modify <filename>otg_whitelist.h</filename>
+	to match its interoperability specification.
+	</emphasis>
+	</para>
+	<para>Non-OTG Linux hosts, like PCs and workstations,
+	normally have some solution for adding drivers, so that
+	peripherals that aren't recognized can eventually be supported.
+	That approach is unreasonable for consumer products that may
+	never have their firmware upgraded, and where it's usually
+	unrealistic to expect traditional PC/workstation/server kinds
+	of support model to work.
+	For example, it's often impractical to change device firmware
+	once the product has been distributed, so driver bugs can't
+	normally be fixed if they're found after shipment.
+	</para></listitem>
+</itemizedlist>
+
+<para>
+Additional changes are needed below those hardware-neutral
+<emphasis>usb_bus</emphasis> and <emphasis>usb_gadget</emphasis>
+driver interfaces; those aren't discussed here in any detail.
+Those affect the hardware-specific code for each USB Host or Peripheral
+controller, and how the HCD initializes (since OTG can be active only
+on a single port).
+They also involve what may be called an <emphasis>OTG Controller
+Driver</emphasis>, managing the OTG transceiver and the OTG state
+machine logic as well as much of the root hub behavior for the
+OTG port.
+The OTG controller driver needs to activate and deactivate USB
+controllers depending on the relevant device role.
+Some related changes were needed inside usbcore, so that it
+can identify OTG-capable devices and respond appropriately
+to HNP or SRP protocols.
+</para> 
+
+</chapter>
 
 </book>
 <!--
diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt	2004-08-09 16:43:25 -07:00
+++ b/Documentation/crypto/api-intro.txt	2004-08-24 11:26:41 -07:00
@@ -227,6 +227,9 @@
 Khazad algorithm contributors:
   Aaron Grothe
 
+Whirlpool algorithm contributors:
+  Aaron Grothe
+
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:
diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt
--- a/Documentation/devices.txt	2004-07-16 08:06:47 -07:00
+++ b/Documentation/devices.txt	2004-08-27 00:02:35 -07:00
@@ -1,9 +1,9 @@
 
 		       LINUX ALLOCATED DEVICES
 
-	     Maintained by John Cagle <device@lanana.org>
+	     Maintained by Torben Mathiasen <device@lanana.org>
 
-		      Last revised: 15 March 2004
+		      Last revised: 04 August 2004
 
 This list is the Linux Device List, the official registry of allocated
 device numbers and /dev directory nodes for the Linux operating
@@ -410,6 +410,7 @@
 		199 = /dev/scanners/cuecat :CueCat barcode scanner
 		200 = /dev/net/tun	TAP/TUN network device
 		201 = /dev/button/gulpb	Transmeta GULP-B buttons
+		202 = /dev/emd/ctl	Enhanced Metadisk RAID (EMD) control
 		204 = /dev/video/em8300		EM8300 DVD decoder control
 		205 = /dev/video/em8300_mv	EM8300 DVD decoder video
 		206 = /dev/video/em8300_ma	EM8300 DVD decoder audio
@@ -1796,14 +1797,15 @@
 		partitions is 15.
 
 103 char	Arla network file system
-		  0 = /dev/xfs0		Arla XFS
+		  0 = /dev/nnpfs0	First NNPFS device
+		  1 = /dev/nnpfs1	Second NNPFS device
 
 		Arla is a free clone of the Andrew File System, AFS.
-		Any resemblance with the Swedish milk producer is
-		coincidental.  For more information about the project,
-		write to <arla-drinkers@stacken.kth.se> or subscribe
-		to the arla announce mailing list by sending a mail to
-		<arla-announce-request@stacken.kth.se>.
+		The NNPFS device gives user mode filesystem
+		implementations a kernel presence for caching and easy
+		mounting.  For more information about the project,
+		write to <arla-drinkers@stacken.kth.se> or see
+		http://www.stacken.kth.se/project/arla/
 
 103 block	Audit device
 		  0 = /dev/audit	Audit device
@@ -2060,12 +2062,10 @@
                 device names.  For example, /dev/hda5 would become
                 /dev/evms/hda5.
 
-118 char	Solidum ???
-		  0 = /dev/solnp0
-		  1 = /dev/solnp1
-		    ...
-		128 = /dev/solnpctl0
-		129 = /dev/solnpctl1
+118 char	IBM Cryptographic Accelerator
+		  0 = /dev/ica	Virtual interface to all IBM Crypto Accelerators
+		  1 = /dev/ica0	IBMCA Device 0
+		  2 = /dev/ica1	IBMCA Device 1
 		    ...
 
 119 char	VMware virtual network control
@@ -2310,6 +2310,11 @@
 		  1 = /dev/aureal1	Second Aureal Vortex
 		    ...
 
+147 block	Distributed Replicated Block Device (DRBD)
+		  0 = /dev/drbd0	First DRBD device
+		  1 = /dev/drbd1	Second DRBD device
+		    ...
+
 148 char	Technology Concepts serial card
 		  0 = /dev/ttyT0	First TCL port
 		  1 = /dev/ttyT1	Second TCL port
@@ -2346,6 +2351,22 @@
 		    ...
 		 15 = /dev/spi15	Sixteenth SPI device on the bus
 
+153 block	Enhanced Metadisk RAID (EMD) storage units
+		  0 = /dev/emd/0	First unit
+		  1 = /dev/emd/0p1	Partition 1 on First unit
+		  2 = /dev/emd/0p2	Partition 2 on First unit
+		    ...
+		 15 = /dev/emd/0p15	Partition 15 on First unit
+
+		 16 = /dev/emd/1	Second unit
+		 32 = /dev/emd/2	Third unit
+		    ...
+		240 = /dev/emd/15	Sixteenth unit
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
 154 char	Specialix RIO serial card
 		  0 = /dev/ttySR0	First RIO port
 		    ...
@@ -2371,23 +2392,24 @@
 		  1 = /dev/gfax1	GammaLink channel 1
 		    ...
 
-159		RESERVED
+159 char	RESERVED
+159 block	RESERVED
 
 160 char	General Purpose Instrument Bus (GPIB)
 		  0 = /dev/gpib0	First GPIB bus
 		  1 = /dev/gpib1	Second GPIB bus
 		    ...
 
-160 block       Promise SX8 8-port SATA Disks on First Controller
-		  0 = /dev/sx8/0     SATA disk 0 whole disk
-		  1 = /dev/sx8/0p1   SATA disk 0 partition 1
+160 block       Carmel 8-port SATA Disks on First Controller
+		  0 = /dev/carmel/0     SATA disk 0 whole disk
+		  1 = /dev/carmel/0p1   SATA disk 0 partition 1
 		    ...
-		 31 = /dev/sx8/0p31  SATA disk 0 partition 31
+		 31 = /dev/carmel/0p31  SATA disk 0 partition 31
 
-		 32 = /dev/sx8/1     SATA disk 1 whole disk
-		 64 = /dev/sx8/2     SATA disk 2 whole disk
+		 32 = /dev/carmel/1     SATA disk 1 whole disk
+		 64 = /dev/carmel/2     SATA disk 2 whole disk
 		    ...
-		224 = /dev/sx8/7     SATA disk 7 whole disk
+		224 = /dev/carmel/7     SATA disk 7 whole disk
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
@@ -2401,16 +2423,16 @@
 		 17 = /dev/irlpt1	Second IrLPT device
 		    ...
 
-161 block       Promise SX8 8-port SATA Disks on Second Controller
-		  0 = /dev/sx8/8     SATA disk 8 whole disk
-		  1 = /dev/sx8/8p1   SATA disk 8 partition 1
+161 block       Carmel 8-port SATA Disks on Second Controller
+		  0 = /dev/carmel/8     SATA disk 8 whole disk
+		  1 = /dev/carmel/8p1   SATA disk 8 partition 1
 		    ...
-		 31 = /dev/sx8/8p31  SATA disk 8 partition 31
+		 31 = /dev/carmel/8p31  SATA disk 8 partition 31
 
-		 32 = /dev/sx8/9     SATA disk 9 whole disk
-		 64 = /dev/sx8/10    SATA disk 10 whole disk
+		 32 = /dev/carmel/9     SATA disk 9 whole disk
+		 64 = /dev/carmel/10    SATA disk 10 whole disk
 		    ...
-		224 = /dev/sx8/15    SATA disk 15 whole disk
+		224 = /dev/carmel/15    SATA disk 15 whole disk
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
@@ -2720,6 +2742,9 @@
 		    ...
 		 39 = /dev/ttyDB7		DataBooster serial port 7
 		 40 = /dev/ttySG0		SGI Altix console port
+		 41 = /dev/ttySMX0		Motorola i.MX - port 0
+		 42 = /dev/ttySMX1		Motorola i.MX - port 1
+		 43 = /dev/ttySMX2		Motorola i.MX - port 2
 
 205 char	Low-density serial ports (alternate device)
 		  0 = /dev/culu0		Callout device for ttyLU0
@@ -2745,6 +2770,9 @@
 		    ...
 		 39 = /dev/cudb7		Callout device for ttyDB7
 		 40 = /dev/cusg0		Callout device for ttySG0
+		 41 = /dev/ttySMX0		Callout device for ttySMX0
+		 42 = /dev/ttySMX1		Callout device for ttySMX1
+		 43 = /dev/ttySMX2		Callout device for ttySMX2
 
 206 char	OnStream SC-x0 tape devices
 		  0 = /dev/osst0		First OnStream SCSI tape, mode 0
diff -Nru a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt
--- a/Documentation/driver-model/bus.txt	2003-04-16 13:57:23 -07:00
+++ b/Documentation/driver-model/bus.txt	2004-08-19 12:32:58 -07:00
@@ -5,20 +5,21 @@
 ~~~~~~~~~~
 
 struct bus_type {
-        char                    * name;
-        rwlock_t                lock;
-        atomic_t                refcount;
-
-        struct list_head        node;
-        struct list_head        devices;
-        struct list_head        drivers;
-
-        struct driver_dir_entry dir;
-        struct driver_dir_entry device_dir;
-        struct driver_dir_entry driver_dir;
+	char			* name;
 
-        int     (*match)        (struct device * dev, struct device_driver * drv);
-	struct device (*add)	(struct device * parent, char * bus_id);
+	struct subsystem	subsys;
+	struct kset		drivers;
+	struct kset		devices;
+
+	struct bus_attribute	* bus_attrs;
+	struct device_attribute	* dev_attrs;
+	struct driver_attribute	* drv_attrs;
+
+	int		(*match)(struct device * dev, struct device_driver * drv);
+	int		(*hotplug) (struct device *dev, char **envp, 
+				    int num_envp, char *buffer, int buffer_size);
+	int		(*suspend)(struct device * dev, u32 state);
+	int		(*resume)(struct device * dev);
 };
 
 int bus_register(struct bus_type * bus);
@@ -47,7 +48,7 @@
 When a bus driver is initialized, it calls bus_register. This
 initializes the rest of the fields in the bus object and inserts it
 into a global list of bus types. Once the bus object is registered, 
-the fields in it (e.g. the rwlock_t) are usable by the bus driver. 
+the fields in it are usable by the bus driver. 
 
 
 Callbacks
@@ -71,40 +72,6 @@
 iterated over, and the match callback is called for each device that
 does not have a driver associated with it. 
 
-add(): Adding a child device
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The add callback is available to notify the bus about a child device
-at a particular location. 
-
-The parent parameter is the parent device of the child to be added. If
-parent == NULL, the bus should add the device as a child of a default
-parent device or as a child of the root. This policy decision is up to
-the bus driver.
-
-The format of the bus_id field should be consistent with the format of
-the bus_id field of the rest of the devices on the bus. This requires
-the caller to know the format.
-
-On return, the bus driver should return a pointer to the device that
-was created. If the device was not created, the bus driver should
-return an appropriate error code. Refer to include/linux/err.h for
-helper functions to encode errors. Some sample code:
-
-struct device * pci_bus_add(struct device * parent, char * bus_id)
-{
-	...
-	/* the device already exists */
-	return ERR_PTR(-EEXIST);
-	...
-}
-
-The caller can check the return value using IS_ERR():
-
-    struct device * newdev = pci_bus_type.add(parent,bus_id);
-    if (IS_ERR(newdev)) {
-	...
-    }
 
 
 Device and Driver Lists
@@ -118,10 +85,11 @@
 
 The LDM core provides helper functions for iterating over each list.
 
-int bus_for_each_dev(struct bus_type * bus, void * data, 
-		     int (*callback)(struct device * dev, void * data));
-int bus_for_each_drv(struct bus_type * bus, void * data,
-		     int (*callback)(struct device_driver * drv, void * data));
+int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
+		     int (*fn)(struct device *, void *));
+
+int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, 
+		     void * data, int (*fn)(struct device_driver *, void *));
 
 These helpers iterate over the respective list, and call the callback
 for each device or driver in the list. All list accesses are
@@ -168,9 +136,9 @@
 Exporting Attributes
 ~~~~~~~~~~~~~~~~~~~~
 struct bus_attribute {
-        struct attribute        attr;
-        ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off);
-        ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off);
+	struct attribute	attr;
+	ssize_t (*show)(struct bus_type *, char * buf);
+	ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
 };
 
 Bus drivers can export attributes using the BUS_ATTR macro that works
diff -Nru a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt
--- a/Documentation/filesystems/ext2.txt	2002-02-04 23:42:14 -08:00
+++ b/Documentation/filesystems/ext2.txt	2004-08-24 02:09:03 -07:00
@@ -17,6 +17,33 @@
 bsddf			(*)	Makes `df' act like BSD.
 minixdf				Makes `df' act like Minix.
 
+barrier=1			This enables/disables barriers. barrier=0 disables it,
+				barrier=1 enables it.
+
+orlov			(*)	This enables the new Orlov block allocator. It's
+				enabled by default.
+
+oldalloc			This disables the Orlov block allocator and
+				enables the old block allocator. Orlov should
+				have better performance, we'd like to get some
+				feedback  if it's the contrary for you.
+
+user_xattr		(*)	Enables POSIX Extended Attributes. It's enabled by
+				default, however you need to confifure its support
+				(CONFIG_EXT2_FS_XATTR). This is neccesary if you want
+				to use POSIX Acces Control Lists support. You can visit
+				http://acl.bestbits.at to know more about POSIX Extended
+				attributes.
+
+nouser_xattr			Disables POSIX Extended Attributes.
+
+acl			(*)	Enables POSIX Access Control Lists support. This is
+				enabled by default, however you need to configure
+				its support (CONFIG_EXT2_FS_POSIX_ACL). If you want
+				to know more about ACLs visit http://acl.bestbits.at
+
+noacl				This option disables POSIX Access Control List support.
+
 check=none, nocheck	(*)	Don't do extra checking of bitmaps on mount
 				(check=normal and check=strict options removed)
 
@@ -336,9 +363,8 @@
 the time of the crash, then there is no guarantee of consistency for
 the blocks in that transaction so they are discarded (which means any
 filesystem changes they represent are also lost).
-
-The ext3 code is currently (Apr 2001) available for 2.2 kernels only,
-and not yet available for 2.4 kernels.
+Check Documentation/filesystems/ext3.txt if you want to read more about
+ext3 and journaling.
 
 References
 ==========
@@ -349,8 +375,6 @@
 Journaling (ext3)	ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/
 Hashed Directories	http://kernelnewbies.org/~phillips/htree/
 Filesystem Resizing	http://ext2resize.sourceforge.net/
-Extended Attributes &
-Access Control Lists	http://acl.bestbits.at/
 Compression (*)		http://www.netspace.net.au/~reiter/e2compr/
 
 Implementations for:
diff -Nru a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
--- a/Documentation/filesystems/ext3.txt	2003-03-11 10:20:18 -08:00
+++ b/Documentation/filesystems/ext3.txt	2004-08-24 02:09:03 -07:00
@@ -22,6 +22,63 @@
 			the inode which will represent the ext3 file
 			system's journal file.
 
+noload			Don't load the journal on mounting.
+
+data=journal		All data are committed into the journal prior
+			to being written into the main file system.
+
+data=ordered	(*)	All data are forced directly out to the main file
+			system prior to its metadata being committed to
+			the journal.
+
+data=writeback		Data ordering is not preserved, data may be
+			written into the main file system after its
+			metadata has been committed to the journal.
+
+commit=nrsec	(*)	Ext3 can be told to sync all its data and metadata
+			every 'nrsec' seconds. The default value is 5 seconds.
+			This means that if you lose your power, you will lose,
+			as much, the latest 5 seconds of work (your filesystem
+			will not be damaged though, thanks to journaling). This
+			default value (or any low value) will hurt performance,
+			but it's good for data-safety. Setting it to 0 will
+			have the same effect than leaving the default 5 sec.
+			Setting it to very large values will improve
+			performance.
+
+barrier=1		This enables/disables barriers. barrier=0 disables it,
+			barrier=1 enables it.
+
+orlov		(*)	This enables the new Orlov block allocator. It's enabled
+			by default.
+
+oldalloc		This disables the Orlov block allocator and enables the
+			old block allocator. Orlov should have better performance,
+			we'd like to get some feedback if it's the contrary for
+			you.
+
+user_xattr	(*)	Enables POSIX Extended Attributes. It's enabled by
+			default, however you need to confifure its support
+			(CONFIG_EXT3_FS_XATTR). This is neccesary if you want
+			to use POSIX Acces Control Lists support. You can visit
+			http://acl.bestbits.at to know more about POSIX Extended
+			attributes.
+
+nouser_xattr		Disables POSIX Extended Attributes.
+
+acl		(*)	Enables POSIX Access Control Lists support. This is
+			enabled by default, however you need to configure
+			its support (CONFIG_EXT3_FS_POSIX_ACL). If you want
+			to know more about ACLs visit http://acl.bestbits.at
+
+noacl			This option disables POSIX Access Control List support.
+
+reservation
+
+noreservation
+
+resize=
+
 bsddf 		(*)	Make 'df' act like BSD.
 minixdf			Make 'df' act like Minix.
 
@@ -30,8 +87,6 @@
 
 debug			Extra debugging information is sent to syslog.
 
-noload			Don't load the journal on mounting.
-
 errors=remount-ro(*)	Remount the filesystem read-only on an error.
 errors=continue		Keep going on a filesystem error.
 errors=panic		Panic and halt the machine if an error occurs.
@@ -48,17 +103,6 @@
 
 sb=n			Use alternate superblock at this location.
 
-data=journal		All data are committed into the journal prior 
-			to being written into the main file system.
-		
-data=ordered	(*)	All data are forced directly out to the main file 
-			system prior to its metadata being committed to 
-			the journal.
-		
-data=writeback  	Data ordering is not preserved, data may be 
-			written into the main file system after its
-			metadata has been committed to the journal.
-
 quota			Quota options are currently silently ignored.
 noquota			(see fs/ext3/super.c, line 594)
 grpquota
@@ -114,7 +158,7 @@
 -------------
 
 Ext2 partitions can be easily convert to ext3, with `tune2fs -j <dev>`.
- Ext3 is fully compatible with Ext2.  Ext3 partitions can easily be
+Ext3 is fully compatible with Ext2.  Ext3 partitions can easily be
 mounted as Ext2.
 
 External Tools
diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
--- a/Documentation/filesystems/proc.txt	2004-08-23 01:14:33 -07:00
+++ b/Documentation/filesystems/proc.txt	2004-08-24 02:08:38 -07:00
@@ -169,16 +169,18 @@
 process memory usage. Its seven fields are explained in Table 1-2.
 
 
-Table 1-2: Contents of the statm files 
+Table 1-2: Contents of the statm files (as of 2.6.8-rc3)
 ..............................................................................
- File     Content                         
- size     total program size              
- resident size of memory portions         
- shared   number of pages that are shared 
- trs      number of pages that are 'code' 
- drs      number of pages of data/stack   
- lrs      number of pages of library      
- dt       number of dirty pages           
+ Field    Content
+ size     total program size (pages)		(same as VmSize in status)
+ resident size of memory portions (pages)	(same as VmRSS in status)
+ shared   number of pages that are shared	(i.e. backed by a file)
+ trs      number of pages that are 'code'	(not including libs; broken,
+							includes data segment)
+ lrs      number of pages of library		(always 0 on 2.6)
+ drs      number of pages of data/stack		(including libs; broken,
+							includes library text)
+ dt       number of dirty pages			(always 0 on 2.6)
 ..............................................................................
 
 1.2 Kernel data
@@ -1173,6 +1175,12 @@
 for writeout by the pdflush daemons.  It is expressed in 100'ths of a second. 
 Data which has been dirty in-memory for longer than this interval will be
 written out next time a pdflush daemon wakes up.
+
+legacy_va_layout
+----------------
+
+If non-zero, this sysctl disables the new 32-bit mmap mmap layout - the kernel
+will use the legacy (2.4) layout for all processes.
 
 lower_zone_protection
 ---------------------
diff -Nru a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface
--- a/Documentation/i2c/sysfs-interface	2004-03-30 12:14:38 -08:00
+++ b/Documentation/i2c/sysfs-interface	2004-08-12 12:57:05 -07:00
@@ -104,7 +104,7 @@
 			in7_*	varies
 			in8_*	varies
 
-in0_ref		CPU core reference voltage.
+cpu[0-1]_vid	CPU core reference voltage.
 		Unit: millivolt
 		Read only.
 		Not always correct.
diff -Nru a/Documentation/i2o/README b/Documentation/i2o/README
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/i2o/README	2004-08-24 11:29:25 -07:00
@@ -0,0 +1,63 @@
+
+	Linux I2O Support	(c) Copyright 1999 Red Hat Software
+					and others.
+
+	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 of the License, or (at your option) any later version.
+
+AUTHORS (so far)
+
+Alan Cox, Building Number Three Ltd.
+	Core code, SCSI and Block OSMs
+
+Steve Ralston, LSI Logic Corp.
+	Debugging SCSI and Block OSM
+
+Deepak Saxena, Intel Corp.
+	Various core/block extensions
+	/proc interface, bug fixes
+	Ioctl interfaces for control
+	Debugging LAN OSM
+
+Philip Rumpf
+	Fixed assorted dumb SMP locking bugs
+
+Juha Sievanen, University of Helsinki Finland
+	LAN OSM code
+	/proc interface to LAN class
+	Bug fixes
+	Core code extensions
+
+Auvo Häkkinen, University of Helsinki Finland
+	LAN OSM code
+	/Proc interface to LAN class
+	Bug fixes
+	Core code extensions
+
+Taneli Vähäkangas, University of Helsinki Finland
+	Fixes to i2o_config
+
+CREDITS
+
+	This work was made possible by
+
+Red Hat Software
+	Funding for the Building #3 part of the project
+
+Symbios Logic (Now LSI)
+	Host adapters, hints, known to work platforms when I hit
+	compatibility problems
+
+BoxHill Corporation
+	Loan of initial FibreChannel disk array used for development work.
+
+European Comission
+	Funding the work done by the University of Helsinki
+
+SysKonnect
+        Loan of FDDI and Gigabit Ethernet cards
+
+ASUSTeK
+        Loan of I2O motherboard
diff -Nru a/Documentation/i2o/ioctl b/Documentation/i2o/ioctl
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/i2o/ioctl	2004-08-24 11:29:27 -07:00
@@ -0,0 +1,394 @@
+
+Linux I2O User Space Interface
+rev 0.3 - 04/20/99
+
+=============================================================================
+Originally written by Deepak Saxena(deepak@plexity.net)
+Currently maintained by Deepak Saxena(deepak@plexity.net)
+=============================================================================
+
+I. Introduction
+
+The Linux I2O subsystem provides a set of ioctl() commands that can be
+utilized by user space applications to communicate with IOPs and devices
+on individual IOPs. This document defines the specific ioctl() commands
+that are available to the user and provides examples of their uses.
+
+This document assumes the reader is familiar with or has access to the
+I2O specification as no I2O message parameters are outlined.  For information
+on the specification, see http://www.i2osig.org
+
+This document and the I2O user space interface are currently maintained
+by Deepak Saxena.  Please send all comments, errata, and bug fixes to
+deepak@csociety.purdue.edu
+
+II. IOP Access
+
+Access to the I2O subsystem is provided through the device file named
+/dev/i2o/ctl.  This file is a character file with major number 10 and minor
+number 166.  It can be created through the following command:
+
+   mknod /dev/i2o/ctl c 10 166
+
+III. Determining the IOP Count
+
+   SYNOPSIS
+
+   ioctl(fd, I2OGETIOPS,  int *count);
+
+   u8 count[MAX_I2O_CONTROLLERS];
+
+   DESCRIPTION
+
+   This function returns the system's active IOP table.  count should
+   point to a buffer containing MAX_I2O_CONTROLLERS entries.  Upon
+   returning, each entry will contain a non-zero value if the given
+   IOP unit is active, and NULL if it is inactive or non-existent.
+
+   RETURN VALUE.
+
+   Returns 0 if no errors occur, and -1 otherwise.  If an error occurs,
+   errno is set appropriately:
+
+     EFAULT   Invalid user space pointer was passed
+
+IV. Getting Hardware Resource Table
+
+   SYNOPSIS
+
+   ioctl(fd, I2OHRTGET, struct i2o_cmd_hrt *hrt);
+
+      struct i2o_cmd_hrtlct
+      {
+         u32   iop;      /* IOP unit number */
+         void  *resbuf;  /* Buffer for result */
+         u32   *reslen;  /* Buffer length in bytes */
+      };
+
+   DESCRIPTION
+
+   This function returns the Hardware Resource Table of the IOP specified
+   by hrt->iop in the buffer pointed to by hrt->resbuf. The actual size of
+   the data is written into *(hrt->reslen).
+
+   RETURNS
+
+   This function returns 0 if no errors occur. If an error occurs, -1
+   is returned and errno is set appropriately:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(hrt->reslen)
+
+V. Getting Logical Configuration Table
+
+   SYNOPSIS
+
+   ioctl(fd, I2OLCTGET, struct i2o_cmd_lct *lct);
+
+      struct i2o_cmd_hrtlct
+      {
+         u32   iop;      /* IOP unit number */
+         void  *resbuf;  /* Buffer for result */
+         u32   *reslen;  /* Buffer length in bytes */
+      };
+
+   DESCRIPTION
+
+   This function returns the Logical Configuration Table of the IOP specified
+   by lct->iop in the buffer pointed to by lct->resbuf. The actual size of
+   the data is written into *(lct->reslen).
+
+   RETURNS
+
+   This function returns 0 if no errors occur. If an error occurs, -1
+   is returned and errno is set appropriately:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(lct->reslen)
+
+VI. Settting Parameters
+
+   SYNOPSIS
+
+   ioctl(fd, I2OPARMSET, struct i2o_parm_setget *ops);
+
+      struct i2o_cmd_psetget
+      {
+         u32   iop;      /* IOP unit number */
+         u32   tid;      /* Target device TID */
+         void  *opbuf;   /* Operation List buffer */
+         u32   oplen;    /* Operation List buffer length in bytes */
+         void  *resbuf;  /* Result List buffer */
+         u32   *reslen;  /* Result List buffer length in bytes */
+      };
+
+   DESCRIPTION
+
+   This function posts a UtilParamsSet message to the device identified
+   by ops->iop and ops->tid.  The operation list for the message is
+   sent through the ops->opbuf buffer, and the result list is written
+   into the buffer pointed to by ops->resbuf.  The number of bytes
+   written is placed into *(ops->reslen).
+
+   RETURNS
+
+   The return value is the size in bytes of the data written into
+   ops->resbuf if no errors occur.  If an error occurs, -1 is returned
+   and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(ops->reslen)
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+   A return value of 0 does not mean that the value was actually
+   changed properly on the IOP.  The user should check the result
+   list to determine the specific status of the transaction.
+
+VII. Getting Parameters
+
+   SYNOPSIS
+
+   ioctl(fd, I2OPARMGET, struct i2o_parm_setget *ops);
+
+      struct i2o_parm_setget
+      {
+         u32   iop;      /* IOP unit number */
+         u32   tid;      /* Target device TID */
+         void  *opbuf;   /* Operation List buffer */
+         u32   oplen;    /* Operation List buffer length in bytes */
+         void  *resbuf;  /* Result List buffer */
+         u32   *reslen;  /* Result List buffer length in bytes */
+      };
+
+   DESCRIPTION
+
+   This function posts a UtilParamsGet message to the device identified
+   by ops->iop and ops->tid.  The operation list for the message is
+   sent through the ops->opbuf buffer, and the result list is written
+   into the buffer pointed to by ops->resbuf.  The actual size of data
+   written is placed into *(ops->reslen).
+
+   RETURNS
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(ops->reslen)
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+   A return value of 0 does not mean that the value was actually
+   properly retreived.  The user should check the result list
+   to determine the specific status of the transaction.
+
+VIII. Downloading Software
+
+   SYNOPSIS
+
+   ioctl(fd, I2OSWDL, struct i2o_sw_xfer *sw);
+
+      struct i2o_sw_xfer
+      {
+         u32   iop;       /* IOP unit number */
+         u8    flags;     /* DownloadFlags field */
+         u8    sw_type;   /* Software type */
+         u32   sw_id;     /* Software ID */
+         void  *buf;      /* Pointer to software buffer */
+         u32   *swlen;    /* Length of software buffer */
+         u32   *maxfrag;  /* Number of fragments */
+         u32   *curfrag;  /* Current fragment number */
+      };
+
+   DESCRIPTION
+
+   This function downloads a software fragment pointed by sw->buf
+   to the iop identified by sw->iop. The DownloadFlags, SwID, SwType
+   and SwSize fields of the ExecSwDownload message are filled in with
+   the values of sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen).
+
+   The fragments _must_ be sent in order and be 8K in size. The last
+   fragment _may_ be shorter, however. The kernel will compute its
+   size based on information in the sw->swlen field.
+
+   Please note that SW transfers can take a long time.
+
+   RETURNS
+
+   This function returns 0 no errors occur. If an error occurs, -1
+   is returned and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+IX. Uploading Software
+
+   SYNOPSIS
+
+   ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw);
+
+      struct i2o_sw_xfer
+      {
+         u32   iop;      /* IOP unit number */
+         u8    flags; 	 /* UploadFlags */
+         u8    sw_type;  /* Software type */
+         u32   sw_id;    /* Software ID */
+         void  *buf;     /* Pointer to software buffer */
+         u32   *swlen;   /* Length of software buffer */
+         u32   *maxfrag; /* Number of fragments */
+         u32   *curfrag; /* Current fragment number */
+      };
+
+   DESCRIPTION
+
+   This function uploads a software fragment from the IOP identified
+   by sw->iop, sw->sw_type, sw->sw_id and optionally sw->swlen fields.
+   The UploadFlags, SwID, SwType and SwSize fields of the ExecSwUpload
+   message are filled in with the values of sw->flags, sw->sw_id,
+   sw->sw_type and *(sw->swlen).
+
+   The fragments _must_ be requested in order and be 8K in size. The
+   user is responsible for allocating memory pointed by sw->buf. The
+   last fragment _may_ be shorter.
+
+   Please note that SW transfers can take a long time.
+
+   RETURNS
+
+   This function returns 0 if no errors occur.  If an error occurs, -1
+   is returned and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+X. Removing Software
+
+   SYNOPSIS
+
+   ioctl(fd, I2OSWDEL, struct i2o_sw_xfer *sw);
+
+      struct i2o_sw_xfer
+      {
+         u32   iop;      /* IOP unit number */
+         u8    flags; 	 /* RemoveFlags */
+         u8    sw_type;  /* Software type */
+         u32   sw_id;    /* Software ID */
+         void  *buf;     /* Unused */
+         u32   *swlen;   /* Length of the software data */
+         u32   *maxfrag; /* Unused */
+         u32   *curfrag; /* Unused */
+      };
+
+   DESCRIPTION
+
+   This function removes software from the IOP identified by sw->iop.
+   The RemoveFlags, SwID, SwType and SwSize fields of the ExecSwRemove message
+   are filled in with the values of sw->flags, sw->sw_id, sw->sw_type and
+   *(sw->swlen). Give zero in *(sw->len) if the value is unknown. IOP uses
+   *(sw->swlen) value to verify correct identication of the module to remove.
+   The actual size of the module is written into *(sw->swlen).
+
+   RETURNS
+
+   This function returns 0 if no errors occur.  If an error occurs, -1
+   is returned and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+X. Validating Configuration
+
+   SYNOPSIS
+
+   ioctl(fd, I2OVALIDATE, int *iop);
+	u32 iop;
+
+   DESCRIPTION
+
+   This function posts an ExecConfigValidate message to the controller
+   identified by iop. This message indicates that the current
+   configuration is accepted. The iop changes the status of suspect drivers
+   to valid and may delete old drivers from its store.
+
+   RETURNS
+
+   This function returns 0 if no erro occur.  If an error occurs, -1 is
+   returned and errno is set appropriatly:
+
+      ETIMEDOUT   Timeout waiting for reply message
+      ENXIO       Invalid IOP number
+
+XI. Configuration Dialog
+
+   SYNOPSIS
+
+   ioctl(fd, I2OHTML, struct i2o_html *htquery);
+      struct i2o_html
+      {
+         u32   iop;      /* IOP unit number */
+         u32   tid;      /* Target device ID */
+         u32   page;     /* HTML page */
+         void  *resbuf;  /* Buffer for reply HTML page */
+         u32   *reslen;  /* Length in bytes of reply buffer */
+         void  *qbuf;    /* Pointer to HTTP query string */
+         u32   qlen;     /* Length in bytes of query string buffer */
+      };
+
+   DESCRIPTION
+
+   This function posts an UtilConfigDialog message to the device identified
+   by htquery->iop and htquery->tid.  The requested HTML page number is
+   provided by the htquery->page field, and the resultant data is stored
+   in the buffer pointed to by htquery->resbuf.  If there is an HTTP query
+   string that is to be sent to the device, it should be sent in the buffer
+   pointed to by htquery->qbuf.  If there is no query string, this field
+   should be set to NULL. The actual size of the reply received is written
+   into *(htquery->reslen).
+
+   RETURNS
+
+   This function returns 0 if no error occur. If an error occurs, -1
+   is returned and errno is set appropriatly:
+
+      EFAULT      Invalid user space pointer was passed
+      ENXIO       Invalid IOP number
+      ENOBUFS     Buffer not large enough.  If this occurs, the required
+                  buffer length is written into *(ops->reslen)
+      ETIMEDOUT   Timeout waiting for reply message
+      ENOMEM      Kernel memory allocation error
+
+XII. Events
+
+    In the process of determining this.  Current idea is to have use
+    the select() interface to allow user apps to periodically poll
+    the /dev/i2o/ctl device for events.  When select() notifies the user
+    that an event is available, the user would call read() to retrieve
+    a list of all the events that are pending for the specific device.
+
+=============================================================================
+Revision History
+=============================================================================
+
+Rev 0.1 - 04/01/99
+- Initial revision
+
+Rev 0.2 - 04/06/99
+- Changed return values to match UNIX ioctl() standard.  Only return values
+  are 0 and -1.  All errors are reported through errno.
+- Added summary of proposed possible event interfaces
+
+Rev 0.3 - 04/20/99
+- Changed all ioctls() to use pointers to user data instead of actual data
+- Updated error values to match the code
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	2004-08-23 01:15:00 -07:00
+++ b/Documentation/kernel-parameters.txt	2004-08-26 23:30:30 -07:00
@@ -579,6 +579,20 @@
 				so, the driver will manage that printer.
 				See also header of drivers/char/lp.c.
 
+	lpj=n		[KNL]
+			Sets loops_per_jiffy to given constant, thus avoiding
+			time-consuming boot-time autodetection (up to 250 ms per
+			CPU). 0 enables autodetection (default). To determine
+			the correct value for your kernel, boot with normal
+			autodetection and see what value is printed. Note that
+			on SMP systems the preset will be applied to all CPUs,
+			which is likely to cause problems if your CPUs need
+			significantly divergent settings. An incorrect value
+			will cause delays in the kernel to be wrong, leading to
+			unpredictable I/O errors and other breakage. Although
+			unlikely, in the extreme case this might damage your
+			hardware.
+
 	ltpc=		[NET]
 			Format: <io>,<irq>,<dma>
 
@@ -752,6 +766,8 @@
 
 	nomce		[IA-32] Machine Check Exception
 
+	noresidual	[PPC] Don't use residual data on PReP machines.
+
 	noresume	[SWSUSP] Disables resume and restore original swap space.
  
 	no-scroll	[VGA] Disables scrollback.
@@ -898,7 +914,10 @@
 			Ranges are in pairs (memory base and size).
 
 	profile=	[KNL] Enable kernel profiling via /proc/profile
-			(param: profile step/bucket size as a power of 2)
+			{ schedule | <number> }
+			(param: schedule - profile schedule points}
+			(param: profile step/bucket size as a power of 2 for
+				statistical time based profiling)
 
 	prompt_ramdisk=	[RAM] List of RAM disks to prompt for floppy disk
 			before loading.
diff -Nru a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
--- a/Documentation/laptop-mode.txt	2004-07-28 21:58:50 -07:00
+++ b/Documentation/laptop-mode.txt	2004-08-24 02:09:00 -07:00
@@ -249,7 +249,7 @@
 # playing.
 #READAHEAD=4096
 
-# Shall we remount journaled fs. with appropiate commit interval? (1=yes)
+# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
 #DO_REMOUNTS=1
 
 # And shall we add the "noatime" option to that as well? (1=yes)
diff -Nru a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.txt
--- a/Documentation/powerpc/hvcs.txt	2004-07-28 21:58:35 -07:00
+++ b/Documentation/powerpc/hvcs.txt	2004-08-27 00:02:38 -07:00
@@ -10,7 +10,7 @@
 
 	       Author(s) :  Ryan S. Arnold <rsa@us.ibm.com>
 		       Date Created: March, 02, 2004
-		       Last Changed: July, 07, 2004
+		       Last Changed: August, 24, 2004
 
 ---------------------------------------------------------------------------
 Table of contents:
@@ -243,6 +243,25 @@
 continue using the previous user's logged in session which includes
 using the $TERM variable that the previous user supplied.
 
+Hotplug add and remove of vty-server adapters affects which /dev/hvcs* node
+is used to connect to each vty-server adapter.  In order to determine which
+vty-server adapter is associated with which /dev/hvcs* node a special sysfs
+attribute has been added to each vty-server sysfs entry.  This entry is
+called "index" and showing it reveals an integer that refers to the
+/dev/hvcs* entry to use to connect to that device.  For instance cating the
+index attribute of vty-server adapter 30000004 shows the following.
+
+	Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat index
+	2
+
+This index of '2' means that in order to connect to vty-server adapter
+30000004 the user should interact with /dev/hvcs2.
+
+It should be noted that due to the system hotplug I/O capabilities of a
+system the /dev/hvcs* entry that interacts with a particular vty-server
+adapter is not guarenteed to remain the same across system reboots.  Look
+in the Q & A section for more on this issue.
+
 ---------------------------------------------------------------------------
 6. Disconnection
 
@@ -328,8 +347,8 @@
 looks like the following:
 
 	Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
-	.   current_vty   devspec  partner_clcs  vterm_state
-	..  detach_state  name     partner_vtys
+	.   current_vty   devspec  name          partner_vtys
+	..  detach_state  index    partner_clcs  vterm_state
 
 Each entry is provided, by default with a "name" attribute.  Reading the
 "name" attribute will reveal the device type as shown in the following
@@ -498,6 +517,20 @@
 A: Yes, if you have dlpar and hotplug enabled for your system and it has
 been built into the kernel the hvcs drivers is configured to dynamically
 handle additions of new devices and removals of unused devices.
+
+---------------------------------------------------------------------------
+Q: For some reason /dev/hvcs* doesn't map to the same vty-server adapter
+after a reboot.  What happened?
+
+A: Assignment of vty-server adapters to /dev/hvcs* entries is always done
+in the order that the adapters are exposed.  Due to hotplug capabilities of
+this driver assignment of hotplug added vty-servers may be in a different
+order than how they would be exposed on module load.  Rebooting or
+reloading the module after dynamic addition may result in the /dev/hvcs*
+and vty-server coupling changing if a vty-server adapter was added in a
+slot inbetween two other vty-server adapters.  Refer to the section above
+on how to determine which vty-server goes with which /dev/hvcs* node.
+Hint; look at the sysfs "index" attribute for the vty-server.
 
 ---------------------------------------------------------------------------
 Q: Can I use /dev/hvcs* as a conduit to another partition and use a tty
diff -Nru a/Documentation/sched-domains.txt b/Documentation/sched-domains.txt
--- a/Documentation/sched-domains.txt	2004-05-10 03:03:57 -07:00
+++ b/Documentation/sched-domains.txt	2004-08-24 02:08:09 -07:00
@@ -5,12 +5,13 @@
 are locklessly updated.
 
 Each scheduling domain spans a number of CPUs (stored in the ->span field).
-A domain's span MUST be a superset of it child's span, and a base domain
-for CPU i MUST span at least i. The top domain for each CPU will generally
-span all CPUs in the system although strictly it doesn't have to, but this
-could lead to a case where some CPUs will never be given tasks to run unless
-the CPUs allowed mask is explicitly set. A sched domain's span means "balance
-process load among these CPUs".
+A domain's span MUST be a superset of it child's span (this restriction could
+be relaxed if the need arises), and a base domain for CPU i MUST span at least
+i. The top domain for each CPU will generally span all CPUs in the system
+although strictly it doesn't have to, but this could lead to a case where some
+CPUs will never be given tasks to run unless the CPUs allowed mask is
+explicitly set. A sched domain's span means "balance process load among these
+CPUs".
 
 Each scheduling domain must have one or more CPU groups (struct sched_group)
 which are organised as a circular one way linked list from the ->groups
@@ -45,6 +46,20 @@
 The implementor should read comments in include/linux/sched.h:
 struct sched_domain fields, SD_FLAG_*, SD_*_INIT to get an idea of
 the specifics and what to tune.
+
+For SMT, the architecture must define CONFIG_SCHED_SMT and provide a
+cpumask_t cpu_sibling_map[NR_CPUS], where cpu_sibling_map[i] is the mask of
+all "i"'s siblings as well as "i" itself.
+
+Architectures may retain the regular override the default SD_*_INIT flags
+while using the generic domain builder in kernel/sched.c if they wish to
+retain the traditional SMT->SMP->NUMA topology (or some subset of that). This
+can be done by #define'ing ARCH_HASH_SCHED_TUNE.
+
+Alternatively, the architecture may completely override the generic domain
+builder by #define'ing ARCH_HASH_SCHED_DOMAIN, and exporting your
+arch_init_sched_domains function. This function will attach domains to all
+CPUs using cpu_attach_domain.
 
 Implementors should change the line
 #undef SCHED_DOMAIN_DEBUG
diff -Nru a/Documentation/sched-stats.txt b/Documentation/sched-stats.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/sched-stats.txt	2004-08-24 02:08:12 -07:00
@@ -0,0 +1,153 @@
+Version 10 of schedstats includes support for sched_domains, which
+hit the mainline kernel in 2.6.7.  Some counters make more sense to be
+per-runqueue; other to be per-domain.  Note that domains (and their associated
+information) will only be pertinent and available on machines utilizing
+CONFIG_SMP.
+
+In version 10 of schedstat, there is at least one level of domain
+statistics for each cpu listed, and there may well be more than one
+domain.  Domains have no particular names in this implementation, but
+the highest numbered one typically arbitrates balancing across all the
+cpus on the machine, while domain0 is the most tightly focused domain,
+sometimes balancing only between pairs of cpus.  At this time, there
+are no architectures which need more than three domain levels. The first
+field in the domain stats is a bit map indicating which cpus are affected
+by that domain.
+
+These fields are counters, and only increment.  Programs which make use
+of these will need to start with a baseline observation and then calculate
+the change in the counters at each subsequent observation.  A perl script
+which does this for many of the fields is available at
+
+    http://eaglet.rain.com/rick/linux/schedstat/
+
+Note that any such script will necessarily be version-specific, as the main
+reason to change versions is changes in the output format.  For those wishing
+to write their own scripts, the fields are described here.
+
+CPU statistics
+--------------
+cpu<N> 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
+
+NOTE: In the sched_yield() statistics, the active queue is considered empty
+    if it has only one process in it, since obviously the process calling
+    sched_yield() is that process.
+
+First four fields are sched_yield() statistics:
+     1) # of times both the active and the expired queue were empty
+     2) # of times just the active queue was empty
+     3) # of times just the expired queue was empty
+     4) # of times sched_yield() was called
+
+Next four are schedule() statistics:
+     5) # of times the active queue had at least one other process on it
+     6) # of times we switched to the expired queue and reused it
+     7) # of times schedule() was called
+     8) # of times schedule() left the processor idle
+
+Next four are active_load_balance() statistics:
+     9) # of times active_load_balance() was called
+    10) # of times active_load_balance() caused this cpu to gain a task
+    11) # of times active_load_balance() caused this cpu to lose a task
+    12) # of times active_load_balance() tried to move a task and failed
+
+Next three are try_to_wake_up() statistics:
+    13) # of times try_to_wake_up() was called
+    14) # of times try_to_wake_up() successfully moved the awakening task
+    15) # of times try_to_wake_up() attempted to move the awakening task
+
+Next two are wake_up_new_task() statistics:
+    16) # of times wake_up_new_task() was called
+    17) # of times wake_up_new_task() successfully moved the new task
+
+Next one is a sched_migrate_task() statistic:
+    18) # of times sched_migrate_task() was called
+
+Next one is a sched_balance_exec() statistic:
+    19) # of times sched_balance_exec() was called
+
+Next three are statistics describing scheduling latency:
+    20) sum of all time spent running by tasks on this processor (in ms)
+    21) sum of all time spent waiting to run by tasks on this processor (in ms)
+    22) # of tasks (not necessarily unique) given to the processor
+
+The last six are statistics dealing with pull_task():
+    23) # of times pull_task() moved a task to this cpu when newly idle
+    24) # of times pull_task() stole a task from this cpu when another cpu
+	was newly idle
+    25) # of times pull_task() moved a task to this cpu when idle
+    26) # of times pull_task() stole a task from this cpu when another cpu
+	was idle
+    27) # of times pull_task() moved a task to this cpu when busy
+    28) # of times pull_task() stole a task from this cpu when another cpu
+	was busy
+
+
+Domain statistics
+-----------------
+One of these is produced per domain for each cpu described. (Note that if
+CONFIG_SMP is not defined, *no* domains are utilized and these lines
+will not appear in the output.)
+
+domain<N> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+
+The first field is a bit mask indicating what cpus this domain operates over.
+
+The next fifteen are a variety of load_balance() statistics:
+
+     1) # of times in this domain load_balance() was called when the cpu
+	was idle
+     2) # of times in this domain load_balance() was called when the cpu
+	was busy
+     3) # of times in this domain load_balance() was called when the cpu
+	was just becoming idle
+     4) # of times in this domain load_balance() tried to move one or more
+	tasks and failed, when the cpu was idle
+     5) # of times in this domain load_balance() tried to move one or more
+	tasks and failed, when the cpu was busy
+     6) # of times in this domain load_balance() tried to move one or more
+	tasks and failed, when the cpu was just becoming idle
+     7) sum of imbalances discovered (if any) with each call to
+	load_balance() in this domain when the cpu was idle
+     8) sum of imbalances discovered (if any) with each call to
+	load_balance() in this domain when the cpu was busy
+     9) sum of imbalances discovered (if any) with each call to
+	load_balance() in this domain when the cpu was just becoming idle
+    10) # of times in this domain load_balance() was called but did not find
+	a busier queue while the cpu was idle
+    11) # of times in this domain load_balance() was called but did not find
+	a busier queue while the cpu was busy
+    12) # of times in this domain load_balance() was called but did not find
+	a busier queue while the cpu was just becoming idle
+    13) # of times in this domain a busier queue was found while the cpu was
+	idle but no busier group was found
+    14) # of times in this domain a busier queue was found while the cpu was
+	busy but no busier group was found
+    15) # of times in this domain a busier queue was found while the cpu was
+	just becoming idle but no busier group was found
+
+Next two are sched_balance_exec() statistics:
+    17) # of times in this domain sched_balance_exec() successfully pushed
+	a task to a new cpu
+    18) # of times in this domain sched_balance_exec() tried but failed to
+	push a task to a new cpu
+
+Next two are try_to_wake_up() statistics:
+    19) # of times in this domain try_to_wake_up() tried to move a task based
+	on affinity and cache warmth
+    20) # of times in this domain try_to_wake_up() tried to move a task based
+	on load balancing
+
+
+/proc/<pid>/schedstat
+----------------
+schedstats also adds a new /proc/<pid/schedstat file to include some of
+the same information on a per-process level.  There are three fields in
+this file correlating to fields 20, 21, and 22 in the CPU fields, but
+they only apply for that process.
+
+A program could be easily written to make use of these extra fields to
+report on how well a particular process or set of processes is faring
+under the scheduler's policies.  A simple version of such a program is
+available at
+    http://eaglet.rain.com/rick/linux/schedstat/v10/latency.c
diff -Nru a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
--- a/Documentation/scsi/ChangeLog.megaraid	2004-06-21 21:36:23 -07:00
+++ b/Documentation/scsi/ChangeLog.megaraid	2004-08-26 15:21:00 -07:00
@@ -1,42 +1,215 @@
-### Version 2.00.3
-Wed Jan 29 09:13:44 EST 200 - Atul Mukker <atulm@lsil.com>
-i.	Change the handshake in ISR while acknowledging interrupts. Write the
-	valid interrupt pattern 0x10001234 as soon as it is read from the
-	outdoor register. In existing driver and on certain platform, invalid
-	command ids were being returned.
+Release Date	: Tue Aug 24 09:43:35 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.3.1 (scsi module), 2.20.2.0 (cmm module)
+Older Version	: 2.20.3.0 (scsi module), 2.20.2.0 (cmm module)
 
-	Also, do not wait on status be become 0xFF, since FW can return this
-	status in certain circumstances.
+i.	Function reordering so that inline functions are defined before they
+	are actually used. It is now mandatory for GCC 3.4.1 (current stable)
 
-	Initialize the numstatus field of mailbox to 0xFF so that we can wait
-	on this wait in next interrupt. Firmware does not change its value
-	unless there are some status to be posted
+	Declare some heavy-weight functions to be non-inlined,
+	megaraid_mbox_build_cmd, megaraid_mbox_runpendq,
+	megaraid_mbox_prepare_pthru, megaraid_mbox_prepare_epthru,
+	megaraid_busywait_mbox
 
-ii.	Specify the logical drive number while issuing the RESERVATION_STATUS
+		- Andrew Morton <akpm@osdl.org>, 08.19.2004
+		linux-scsi mailing list
 
-iii.	Reduce the default mailbox busy wait time from 300us to 10us. This is
-	done to avaoid a possible deadlock in FW because of longer bust waits.
+	"Something else to clean up after inclusion: every instance of an
+	inline function is actually rendered as a full function call, because
+	the function is always used before it is defined.  Atul, please
+	re-arrange the code to eliminate the need for most (all) of the
+	function prototypes at the top of each file, and define (not just
+	declare with a prototype) each inline function before its first use"
 
-iv.	The max outstanding commands are reduced to 126 because that't the
-	safest value on all FW.
+		- Matt Domsch <Matt_Domsch@dell.com>, 07.27.2004
+		linux-scsi mailing list
 
-v.	Number of sectors per IO are reduced to 128 (64kb), becuase FW needs
-	resources in special circumstances like check consistency, rebuilds
-	etc.
 
-vi.	max_commands is no longer a module parameter because of iv.
+ii.	Display elapsed time (countdown) while waiting for FW to boot.
 
-### Version: 2.00.2
-i.	Intermediate release with kernel specific code
+iii.	Module compilation reorder in Makefile so that unresolved symbols do
+	not occur when driver is compiled non-modular.
 
+		Patrick J. LoPresti <patl@users.sourceforge.net>, 8.22.2004
+		linux-scsi mailing list
 
-### Version: 2.00.1i
-Wed Dec  4 14:34:51 EST 2002 - Atul Mukker <atulm@lsil.com>
-i.	Making the older IO based controllers to work with this driver
 
+Release Date	: Thu Aug 19 09:58:33 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.3.0 (scsi module), 2.20.2.0 (cmm module)
+Older Version	: 2.20.2.0 (scsi module), 2.20.1.0 (cmm module)
 
-### Version 2.00.1
-Fri Nov 15 10:59:44 EST 2002 - Atul Mukker <atulm@lsil.com>
-i.	Release host lock before issuing internal command to reset
-	reservations in megaraid_reset() and reacquire after internal command
-	is completed.
+i.	When copying the mailbox packets, copy only first 14 bytes (for 32-bit
+	mailboxes) and only first 22 bytes (for 64-bit mailboxes). This is to
+	avoid getting the stale values for busy bit. We want to set the busy
+	bit just before issuing command to the FW.
+
+ii.	In the reset handling, if the reseted command is not owned by the
+	driver, do not (wrongly) print information for the "attached" driver
+	packet.
+
+iii.	Have extended wait when issuing command in synchronous mode. This is
+	required for the cases where the option ROM is disabled and there is
+	no BIOS to start the controller. The FW starts to boot after receiving
+	the first command from the driver. The current driver has 1 second
+	timeout for the synchronous commands, which is far less than what is
+	actually required. We now wait up to MBOX_RESET_TIME (180 seconds) for
+	FW boot process.
+
+iv.	In megaraid_mbox_product_info, clear the mailbox contents completely
+	before preparing the command for inquiry3. This is to ensure that the
+	FW does not get junk values in the command.
+
+v.	Do away with the redundant LSI_CONFIG_COMPAT redefinition for
+	CONFIG_COMPAT. Replace <asm/ioctl32.h> with <linux/ioctl32.h>
+
+		- James Bottomley <James.Bottomley@SteelEye.com>, 08.17.2004
+		 linux-scsi mailing list
+
+vi.	Add support for 64-bit applications. Current drivers assume only
+	32-bit applications, even on 64-bit platforms. Use the "data" and
+	"buffer" fields of the mimd_t structure, instead of embedded 32-bit
+	addresses in application mailbox and passthru structures.
+
+vii.	Move the function declarations for the management module from
+	megaraid_mm.h to megaraid_mm.c
+
+		- Andrew Morton <akpm@osdl.org>, 08.19.2004
+		linux-scsi mailing list
+
+viii.	Change default values for MEGARAID_NEWGEN, MEGARAID_MM, and
+	MEGARAID_MAILBOX to 'n' in Kconfig.megaraid
+
+		- Andrew Morton <akpm@osdl.org>, 08.19.2004
+		linux-scsi mailing list
+
+ix.	replace udelay with msleep
+
+x.	Typos corrected in comments and whitespace adjustments, explicit
+	grouping of expressions.
+
+
+Release Date	: Fri Jul 23 15:22:07 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.2.0 (scsi module), 2.20.1.0 (cmm module)
+Older Version	: 2.20.1.0 (scsi module), 2.20.0.0 (cmm module)
+
+i.	Add PCI ids for Acer ROMB 2E solution
+
+ii.	Add PCI ids for I4
+
+iii.	Typo corrected for subsys id for megaraid sata 300-4x
+
+iv.	Remove yield() while mailbox handshake in synchronous commands
+
+
+	"My other main gripe is things like this:
+
+	+	// wait for maximum 1 second for status to post
+	+	for (i = 0; i < 40000; i++) {
+	+		if (mbox->numstatus != 0xFF) break;
+	+		udelay(25); yield();
+	+	}
+
+	which litter the driver.  Use of yield() in drivers is deprecated."
+
+		- James Bottomley <James.Bottomley@SteelEye.com>, 07.14.2004
+		 linux-scsi mailing list
+
+v.	Remove redundant __megaraid_busywait_mbox routine
+
+vi.	Fix bug in the managment module, which causes a system lockup when the
+	IO module is loaded and then unloaded, followed by executing any
+	management utility. The current version of management module does not
+	handle the adapter unregister properly.
+
+	Specifically, it still keeps a reference to the unregistered
+	controllers. To avoid this, the static array adapters has been
+	replaced by a dynamic list, which gets updated every time an adapter
+	is added or removed.
+
+	Also, during unregistration of the IO module, the resources are
+	now released in the exact reverse order of the allocation time
+	sequence.
+
+
+Release Date	: Fri Jun 25 18:58:43 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.1.0
+Older Version	: megaraid 2.20.0.1
+
+i.	Stale list pointer in adapter causes kernel panic when module
+	megaraid_mbox is unloaded
+
+
+Release Date	: Thu Jun 24 20:37:11 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.0.1
+Older Version	: megaraid 2.20.0.00
+
+i.	Modules are not 'y' by default, but depend on current definition of
+	SCSI & PCI.
+
+ii.	Redundant structure mraid_driver_t removed.
+
+iii.	Miscellaneous indentation and goto/label fixes.
+		- Christoph Hellwig <hch@infradead.org>, 06.24.2004 linux-scsi
+
+iv.	scsi_host_put(), do just before completing HBA shutdown.
+
+
+
+Release Date	: Mon Jun 21 19:53:54 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.0.0
+Older Version	: megaraid 2.20.0.rc2 and 2.00.3
+
+i.	Independent module to interact with userland applications and
+	multiplex command to low level RAID module(s).
+
+	"Shared code in a third module, a "library module", is an acceptable
+	solution. modprobe automatically loads dependent modules, so users
+	running "modprobe driver1" or "modprobe driver2" would automatically
+	load the shared library module."
+
+		- Jeff Garzik <jgarzik@pobox.com> 02.25.2004 LKML
+
+	"As Jeff hinted, if your userspace<->driver API is consistent between
+	your new MPT-based RAID controllers and your existing megaraid driver,
+	then perhaps you need a single small helper module (lsiioctl or some
+	better name), loaded by both mptraid and megaraid automatically, which
+	handles registering the /dev/megaraid node dynamically. In this case,
+	both mptraid and megaraid would register with lsiioctl for each
+	adapter discovered, and lsiioctl would essentially be a switch,
+	redirecting userspace tool ioctls to the appropriate driver."
+
+		- Matt Domsch <Matt_Domsch@dell.com> 02.25.2004 LKML
+
+ii.	Remove C99 initializations from pci_device id.
+
+	"pci_id_table_g would be much more readable when not using C99
+	initializers.
+	PCI table doesn't change, there's lots of users that prefer the more
+	readable variant.  And it's really far less and much easier to grok
+	lines without C99 initializers."
+
+		- Christoph Hellwig <hch@infradead.org>, 05.28.2004 linux-scsi
+
+iii.	Many fixes as suggested by Christoph Hellwig <hch@infradead.org> on
+	linux-scsi, 05.28.2004
+
+iv.	We now support up to 32 parallel ioctl commands instead of current 1.
+	There is a conscious effort to let memory allocation not fail for ioctl
+	commands.
+
+v.	Do away with internal memory management. Use pci_pool_(create|alloc)
+	instead.
+
+vi.	Kill tasklet when unloading the driver.
+
+vii.	Do not use "host_lock', driver has fine-grain locks now to protect all
+	data structures.
+
+viii.	Optimize the build scatter-gather list routine. The callers already
+	know the data transfer address and length.
+
+ix.	Better implementation of error handling and recovery. Driver now
+	performs extended errors recovery for instances like scsi cable pull.
+
+x.	Disassociate the management commands with an overlaid scsi command.
+	Driver now treats the management packets as special packets and has a
+	dedicated callback routine.
diff -Nru a/Documentation/scsi/megaraid.txt b/Documentation/scsi/megaraid.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/scsi/megaraid.txt	2004-08-22 08:58:41 -07:00
@@ -0,0 +1,70 @@
+			Notes on Management Module
+			~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Overview:
+--------
+
+Different classes of controllers from LSI Logic, accept and respond to the
+user applications in a similar way. They understand the same firmware control
+commands. Furthermore, the applications also can treat different classes of
+the controllers uniformly. Hence it is logical to have a single module that
+interefaces with the applications on one side and all the low level drivers
+on the other.
+
+The advantages, though obvious, are listed for completeness:
+
+	i.	Avoid duplicate code from the low level drivers.
+	ii.	Unburden the low level drivers from having to export the
+		character node device and related handling.
+	iii.	Implement any policy mechanisms in one place.
+	iv.	Applications have to interface with only module instead of
+		multiple low level drivers.
+
+Currently this module (called Common Management Module) is used only to issue
+ioctl commands. But this module is envisioned to handle all user space level
+interactions. So any 'proc', 'sysfs' implementations will be localized in this
+common module.
+
+Credits:
+-------
+
+"Shared code in a third module, a "library module", is an acceptable
+solution. modprobe automatically loads dependent modules, so users
+running "modprobe driver1" or "modprobe driver2" would automatically
+load the shared library module."
+
+		- Jeff Garzik (jgarzik@pobox.com), 02.25.2004 LKML
+
+"As Jeff hinted, if your userspace<->driver API is consistent between
+your new MPT-based RAID controllers and your existing megaraid driver,
+then perhaps you need a single small helper module (lsiioctl or some
+better name), loaded by both mptraid and megaraid automatically, which
+handles registering the /dev/megaraid node dynamically. In this case,
+both mptraid and megaraid would register with lsiioctl for each
+adapter discovered, and lsiioctl would essentially be a switch,
+redirecting userspace tool ioctls to the appropriate driver."
+
+		- Matt Domsch, (Matt_Domsch@dell.com), 02.25.2004 LKML
+
+Design:
+------
+
+The Common Management Module is implemented in megaraid_mm.[ch] files. This
+module acts as a registry for low level hba drivers. The low level drivers
+(currently only megaraid) register each controller with the common module.
+
+The applications interface with the common module via the character device
+node exported by the module.
+
+The lower level drivers now understand only a new improved ioctl packet called
+uioc_t. The management module converts the older ioctl packets from the older
+applications into uioc_t. After driver handles the uioc_t, the common module
+will convert that back into the old format before returning to applications.
+
+As new applications evolve and replace the old ones, the old packet format 
+will be retired.
+
+Common module dedicates one uioc_t packet to each controller registered. This
+can easily be more than one. But since megaraid is the only low level driver
+today, and it can handle only one ioctl, there is no reason to have more. But
+as new controller classes get added, this will be tuned appropriately.
diff -Nru a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
--- a/Documentation/scsi/scsi_mid_low_api.txt	2004-08-02 01:00:45 -07:00
+++ b/Documentation/scsi/scsi_mid_low_api.txt	2004-08-24 20:25:48 -07:00
@@ -35,7 +35,7 @@
 The SCSI mid level isolates an LLD from other layers such as the SCSI
 upper layer drivers and the block layer.
 
-This version of the document roughly matches linux kernel version 2.6.0-test4.
+This version of the document roughly matches linux kernel version 2.6.8 .
 
 Documentation
 =============
@@ -323,6 +323,16 @@
         instance. If the reference count reaches 0 then the given instance
         is freed
 
+The Scsi_device structure has had reference counting infrastructure added.
+This effectively spreads the ownership of struct Scsi_device instances
+across the various SCSI layers which use them. Previously such instances
+were exclusively owned by the mid level. See the access functions declared
+towards the end of include/scsi/scsi_device.h . If an LLD wants to keep
+a copy of a pointer to a Scsi_device instance it should use scsi_device_get()
+to bump its reference count. When it is finished with the pointer it can
+use scsi_device_put() to decrement its reference count (and potentially
+delete it).
+
 ^^ struct Scsi_Host actually has 2 reference counts which are manipulated
 in parallel by these functions.
 
@@ -416,7 +426,7 @@
 /**
  * scsi_add_host - perform sysfs registration and SCSI bus scan.
  * @shost:   pointer to scsi host instance
- * @dev:     pointer to struct device host instance
+ * @dev:     pointer to struct device of type scsi class
  *
  *      Returns 0 on success, negative errno of failure (e.g. -ENOMEM)
  *
@@ -453,7 +463,7 @@
 
 /**
  * scsi_adjust_queue_depth - change the queue depth on a SCSI device
- * @SDpnt:      pointer to SCSI device to change queue depth on
+ * @sdev:       pointer to SCSI device to change queue depth on
  * @tagged:     0 - no tagged queuing
  *              MSG_SIMPLE_TAG - simple (unordered) tagged queuing
  *              MSG_ORDERED_TAG - ordered tagged queuing
@@ -474,8 +484,8 @@
  *      Defined in: drivers/scsi/scsi.c [see source code for more notes]
  *
  **/
-void scsi_adjust_queue_depth(struct scsi_device * SDpnt, int tagged, 
-                             int num_tags)
+void scsi_adjust_queue_depth(struct scsi_device * sdev, int tagged, 
+                             int tags)
 
 
 /**
@@ -510,7 +520,7 @@
 /**
  * scsi_block_requests - prevent further commands being queued to given host
  *
- * @SHpnt: pointer to host to block commands on
+ * @shost: pointer to host to block commands on
  *
  *      Returns nothing
  *
@@ -521,7 +531,7 @@
  *
  *      Defined in: drivers/scsi/scsi_lib.c
 **/
-void scsi_block_requests(struct Scsi_Host * SHpnt)
+void scsi_block_requests(struct Scsi_Host * shost)
 
 
 /**
@@ -543,9 +553,10 @@
 
 
 /**
- * scsi_host_alloc - create and register a scsi host adapter instance.
- * @shost_tp:   pointer to scsi host template
- * @xtr_bytes:  extra bytes to allocate in hostdata array (which is the
+ * scsi_host_alloc - create a scsi host adapter instance and perform basic
+ *                   initialization.
+ * @sht:        pointer to scsi host template
+ * @privsize:   extra bytes to allocate in hostdata array (which is the
  *              last member of the returned Scsi_Host instance)
  *
  *      Returns pointer to new Scsi_Host instance or NULL on failure
@@ -555,12 +566,15 @@
  *      Notes: When this call returns to the LLD, the SCSI bus scan on
  *      this host has _not_ yet been done.
  *      The hostdata array (by default zero length) is a per host scratch 
- *      area for the LLD.
+ *      area for the LLD's exclusive use.
  *      Both associated refcounting objects have their refcount set to 1.
+ *      Full registration (in sysfs) and a bus scan are performed later when
+ *      scsi_add_host() is called.
  *
  *      Defined in: drivers/scsi/hosts.c .
  **/
-struct Scsi_Host * scsi_host_alloc(struct scsi_host_template *, int xtr_bytes)
+struct Scsi_Host * scsi_host_alloc(struct scsi_host_template * sht,
+                                   int privsize)
 
 
 /**
@@ -619,8 +633,8 @@
 
 /**
  * scsi_register - create and register a scsi host adapter instance.
- * @shost_tp:   pointer to scsi host template
- * @xtr_bytes:  extra bytes to allocate in hostdata array (which is the
+ * @sht:        pointer to scsi host template
+ * @privsize:   extra bytes to allocate in hostdata array (which is the
  *              last member of the returned Scsi_Host instance)
  *
  *      Returns pointer to new Scsi_Host instance or NULL on failure
@@ -634,7 +648,8 @@
  *
  *      Defined in: drivers/scsi/hosts.c .
  **/
-struct Scsi_Host * scsi_register(struct scsi_host_template *, int xtr_bytes)
+struct Scsi_Host * scsi_register(struct scsi_host_template * sht,
+                                 int privsize)
 
 
 /**
@@ -711,15 +726,17 @@
  * scsi_to_pci_dma_dir - convert SCSI subsystem direction flag to PCI
  * @scsi_data_direction: SCSI subsystem direction flag
  *
- *      Returns PCI_DMA_TODEVICE given SCSI_DATA_WRITE,
- *              PCI_DMA_FROMDEVICE given SCSI_DATA_READ
- *              PCI_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
- *              else returns PCI_DMA_NONE
+ *      Returns DMA_TO_DEVICE given SCSI_DATA_WRITE,
+ *              DMA_FROM_DEVICE given SCSI_DATA_READ
+ *              DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
+ *              else returns DMA_NONE
  *
  *      Might block: no
  *
  *      Notes: The SCSI subsystem now uses the same values for these
  *      constants as the PCI subsystem so this function is a nop.
+ *      The recommendation is not to use this conversion function anymore
+ *      (in the 2.6 kernel series) as it is not needed.
  *
  *      Defined in: drivers/scsi/scsi.h .
  **/
@@ -730,13 +747,15 @@
  * scsi_to_sbus_dma_dir - convert SCSI subsystem direction flag to SBUS
  * @scsi_data_direction: SCSI subsystem direction flag
  *
- *      Returns SBUS_DMA_TODEVICE given SCSI_DATA_WRITE,
- *              SBUS_DMA_FROMDEVICE given SCSI_DATA_READ
- *              SBUS_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
- *              else returns SBUS_DMA_NONE
+ *      Returns DMA_TO_DEVICE given SCSI_DATA_WRITE,
+ *              FROM_DEVICE given SCSI_DATA_READ
+ *              DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
+ *              else returns DMA_NONE
  *
  *      Notes: The SCSI subsystem now uses the same values for these
  *      constants as the SBUS subsystem so this function is a nop.
+ *      The recommendation is not to use this conversion function anymore
+ *      (in the 2.6 kernel series) as it is not needed.
  *
  *      Might block: no
  *
@@ -749,7 +768,7 @@
  * scsi_track_queue_full - track successive QUEUE_FULL events on given
  *                      device to determine if and when there is a need
  *                      to adjust the queue depth on the device.
- * @SDptr: pointer to SCSI device instance
+ * @sdev:  pointer to SCSI device instance
  * @depth: Current number of outstanding SCSI commands on this device,
  *         not counting the one returned as QUEUE_FULL.
  *
@@ -765,13 +784,13 @@
  *
  *      Defined in: drivers/scsi/scsi.c .
  **/
-int scsi_track_queue_full(Scsi_Device *SDptr, int depth)
+int scsi_track_queue_full(Scsi_Device *sdev, int depth)
 
 
 /**
  * scsi_unblock_requests - allow further commands to be queued to given host
  *
- * @SHpnt: pointer to host to unblock commands on
+ * @shost: pointer to host to unblock commands on
  *
  *      Returns nothing
  *
@@ -779,7 +798,7 @@
  *
  *      Defined in: drivers/scsi/scsi_lib.c .
 **/
-void scsi_unblock_requests(struct Scsi_Host * SHpnt)
+void scsi_unblock_requests(struct Scsi_Host * shost)
 
 
 /**
@@ -901,20 +920,20 @@
  *
  *      Returns:
  *
- *	EH_HANDLED:		I fixed the error, please complete the command
- *	EH_RESET_TIMER:		I need more time, reset the timer and
- *				begin counting again
- *	EH_NOT_HANDLED		Begin normal error recovery
-
+ *      EH_HANDLED:             I fixed the error, please complete the command
+ *      EH_RESET_TIMER:         I need more time, reset the timer and
+ *                              begin counting again
+ *      EH_NOT_HANDLED          Begin normal error recovery
+ *
  *
  *      Locks: None held
  *
  *      Calling context: interrupt
  *
- *	Notes: This is to give the LLD an opportunity to do local recovery.
- *	This recovery is limited to determining if the outstanding command
- *	will ever complete.  You may not abort and restart the command from
- *	this callback.
+ *      Notes: This is to give the LLD an opportunity to do local recovery.
+ *      This recovery is limited to determining if the outstanding command
+ *      will ever complete.  You may not abort and restart the command from
+ *      this callback.
  *
  *      Optionally defined in: LLD
  **/
@@ -1110,7 +1129,7 @@
  *      Optionally defined in: LLD
  **/
     int proc_info(char * buffer, char ** start, off_t offset, 
-                  int length, int hostno, int writeto1_read0)
+                  int length, int host_no, int writeto1_read0)
 
 
 /**
@@ -1120,42 +1139,42 @@
  *
  *      Returns 0 on success.
  *
- *	If there's a failure, return either:
+ *      If there's a failure, return either:
  *
- *	SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
- *	SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
+ *      SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
+ *      SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
  *
- *	On both of these returns, the mid-layer will requeue the I/O
+ *      On both of these returns, the mid-layer will requeue the I/O
  *
- *	- if the return is SCSI_MLQUEUE_DEVICE_BUSY, only that particular
- *	device will be paused, and it will be unpaused when a command to
- *	the device returns (or after a brief delay if there are no more
- *	outstanding commands to it).  Commands to other devices continue
- *	to be processed normally.
- *
- *	- if the return is SCSI_MLQUEUE_HOST_BUSY, all I/O to the host
- *	is paused and will be unpaused when any command returns from
- *	the host (or after a brief delay if there are no outstanding
- *	commands to the host).
- *
- *	For compatibility with earlier versions of queuecommand, any
- *	other return value is treated the same as
- *	SCSI_MLQUEUE_HOST_BUSY.
- *
- *	Other types of errors that are detected immediately may be
- *	flagged by setting scp->result to an appropriate value,
- *	invoking the 'done' callback, and then returning 0 from this
- *	function. If the command is not performed immediately (and the
- *	LLD is starting (or will start) the given command) then this
- *	function should place 0 in scp->result and return 0.
- *
- *	Command ownership.  If the driver returns zero, it owns the
- *	command and must take responsibility for ensuring the 'done'
- *	callback is executed.  Note: the driver may call done before
- *	returning zero, but after it has called done, it may not
- *	return any value other than zero.  If the driver makes a
- *	non-zero return, it must not execute the command's done
- *	callback at any time.
+ *      - if the return is SCSI_MLQUEUE_DEVICE_BUSY, only that particular
+ *      device will be paused, and it will be unpaused when a command to
+ *      the device returns (or after a brief delay if there are no more
+ *      outstanding commands to it).  Commands to other devices continue
+ *      to be processed normally.
+ *
+ *      - if the return is SCSI_MLQUEUE_HOST_BUSY, all I/O to the host
+ *      is paused and will be unpaused when any command returns from
+ *      the host (or after a brief delay if there are no outstanding
+ *      commands to the host).
+ *
+ *      For compatibility with earlier versions of queuecommand, any
+ *      other return value is treated the same as
+ *      SCSI_MLQUEUE_HOST_BUSY.
+ *
+ *      Other types of errors that are detected immediately may be
+ *      flagged by setting scp->result to an appropriate value,
+ *      invoking the 'done' callback, and then returning 0 from this
+ *      function. If the command is not performed immediately (and the
+ *      LLD is starting (or will start) the given command) then this
+ *      function should place 0 in scp->result and return 0.
+ *
+ *      Command ownership.  If the driver returns zero, it owns the
+ *      command and must take responsibility for ensuring the 'done'
+ *      callback is executed.  Note: the driver may call done before
+ *      returning zero, but after it has called done, it may not
+ *      return any value other than zero.  If the driver makes a
+ *      non-zero return, it must not execute the command's done
+ *      callback at any time.
  *
  *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
  *             and is expected to be held on return.
@@ -1317,7 +1336,12 @@
     sg_tablesize - maximum scatter gather elements allowed by host.
                    0 implies scatter gather not supported by host
     max_sectors  - maximum number of sectors (usually 512 bytes) allowed
-                   in a single SCSI command. 0 implies no maximum.
+                   in a single SCSI command. The default value of 0 leads
+                   to a setting of SCSI_DEFAULT_MAX_SECTORS (defined in
+                   scsi_host.h) which is currently set to 1024. So for a
+                   disk the maximum transfer size is 512 KB when max_sectors
+                   is not defined. Note that this size may not be sufficient
+                   for disk firmware uploads.
     cmd_per_lun  - maximum number of commands that can be queued on devices
                    controlled by the host. Overridden by LLD calls to
                    scsi_adjust_queue_depth().
@@ -1328,6 +1352,9 @@
                      0=>disallow SCSI command merging
     hostt        - pointer to driver's struct scsi_host_template from which
                    this struct Scsi_Host instance was spawned
+    hostt->proc_name  - name of LLD. This is the driver name that sysfs uses
+    transportt   - pointer to driver's struct scsi_transport_template instance
+                   (if any). FC and SPI transports currently supported.
     sh_list      - a double linked list of pointers to all struct Scsi_Host
                    instances (currently ordered by ascending host_no)
     my_devices   - a double linked list of pointers to struct scsi_device 
@@ -1335,7 +1362,8 @@
     hostdata[0]  - area reserved for LLD at end of struct Scsi_Host. Size
                    is set by the second argument (named 'xtr_bytes') to
                    scsi_host_alloc() or scsi_register().
-The structure is defined in include/scsi/scsi_host.h
+
+The scsi_host structure is defined in include/scsi/scsi_host.h
 
 struct scsi_device
 ------------------
@@ -1347,11 +1375,66 @@
 struct scsi_cmnd
 ----------------
 Instances of this structure convey SCSI commands to the LLD and responses
-back to the mid level. The SCSI mid level will ensure that no more SCSI 
-commands become queued against the LLD than are indicated by 
-scsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will 
-be at least one instance of struct scsi_cmnd available for each SCSI device. 
-The structure is defined in include/scsi/scsi_cmnd.h
+back to the mid level. The SCSI mid level will ensure that no more SCSI
+commands become queued against the LLD than are indicated by
+scsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will
+be at least one instance of struct scsi_cmnd available for each SCSI device.
+Members of interest:
+    cmnd         - array containing SCSI command
+    cmnd_len     - length (in bytes) of SCSI command
+    sc_data_direction - direction of data transfer in data phase. See
+                "enum dma_data_direction" in include/linux/dma-mapping.h
+    request_bufflen - number of data bytes to transfer (0 if no data phase)
+    use_sg       - ==0 -> no scatter gather list, hence transfer data
+                          to/from request_buffer
+                 - >0 ->  scatter gather list (actually an array) in
+                          request_buffer with use_sg elements
+    request_buffer - either contains data buffer or scatter gather list
+                     depending on the setting of use_sg. Scatter gather
+                     elements are defined by 'struct scatterlist' found
+                     in include/asm/scatterlist.h .
+    done         - function pointer that should be invoked by LLD when the
+                   SCSI command is completed (successfully or otherwise).
+                   Should only be called by an LLD if the LLD has accepted
+                   the command (i.e. queuecommand() returned or will return
+                   0). The LLD may invoke 'done'  prior to queuecommand()
+                   finishing.
+    result       - should be set by LLD prior to calling 'done'. A value
+                   of 0 implies a successfully completed command (and all
+                   data (if any) has been transferred to or from the SCSI
+                   target device). 'result' is a 32 bit unsigned integer that
+                   can be viewed as 4 related bytes. The SCSI status value is
+                   in the LSB. See include/scsi/scsi.h status_byte(),
+                   msg_byte(), host_byte() and driver_byte() macros and
+                   related constants.
+    sense_buffer - an array (maximum size: SCSI_SENSE_BUFFERSIZE bytes) that
+                   should be written when the SCSI status (LSB of 'result')
+                   is set to CHECK_CONDITION (2). When CHECK_CONDITION is
+                   set, if the top nibble of sense_buffer[0] has the value 7
+                   then the mid level will assume the sense_buffer array
+                   contains a valid SCSI sense buffer; otherwise the mid
+                   level will issue a REQUEST_SENSE SCSI command to
+                   retrieve the sense buffer. The latter strategy is error
+                   prone in the presence of command queuing so the LLD should
+                   always "auto-sense".
+    device       - pointer to scsi_device object that this command is
+                   associated with.
+    resid        - an LLD should set this signed integer to the requested
+                   transfer length (i.e. 'request_bufflen') less the number
+                   of bytes that are actually transferred. 'resid' is
+                   preset to 0 so an LLD can ignore it if it cannot detect
+                   underruns (overruns should be rare). If possible an LLD
+                   should set 'resid' prior to invoking 'done'. The most
+                   interesting case is data transfers from a SCSI target
+                   device device (i.e. READs) that underrun. 
+    underflow    - LLD should place (DID_ERROR << 16) in 'result' if
+                   actual number of bytes transferred is less than this
+                   figure. Not many LLDs implement this check and some that
+                   do just output an error message to the log rather than
+                   report a DID_ERROR. Better for an LLD to implement
+                   'resid'.
+
+The scsi_cmnd structure is defined in include/scsi/scsi_cmnd.h
 
 
 Locks
@@ -1420,15 +1503,16 @@
 Credits
 =======
 The following people have contributed to this document:
-        Mike Anderson <andmike@us.ibm.com>
-        James Bottomley <James.Bottomley@steeleye.com> 
-        Patrick Mansfield <patmans@us.ibm.com> 
-        Christoph Hellwig <hch@infradead.org>
-        Doug Ledford <dledford@redhat.com>
-        Andries Brouwer <Andries.Brouwer@cwi.nl>
-        Randy Dunlap <rddunlap@osdl.org>
+        Mike Anderson <andmike at us dot ibm dot com>
+        James Bottomley <James dot Bottomley at steeleye dot com> 
+        Patrick Mansfield <patmans at us dot ibm dot com> 
+        Christoph Hellwig <hch at infradead dot org>
+        Doug Ledford <dledford at redhat dot com>
+        Andries Brouwer <Andries dot Brouwer at cwi dot nl>
+        Randy Dunlap <rddunlap at osdl dot org>
+        Alan Stern <stern at rowland dot harvard dot edu>
 
 
 Douglas Gilbert
-dgilbert@interlog.com
-29th August 2003
+dgilbert at interlog dot com
+25th August 2004
diff -Nru a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
--- a/Documentation/sound/alsa/ALSA-Configuration.txt	2004-05-06 20:18:59 -07:00
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt	2004-08-03 01:17:01 -07:00
@@ -188,6 +188,13 @@
 
     This module supports up to 8 cards and autoprobe.
 
+  Module snd-atiixp-modem
+  -----------------------
+
+    Module for ATI IXP 150/200/250 AC97 modem controllers.
+
+    Module supports up to 8 cards.
+
   Module snd-au8810, snd-au8820, snd-au8830
   -----------------------------------------
 
@@ -516,6 +523,13 @@
 
     Module for ForteMedia FM801 based PCI soundcards.
 
+    tea575x_tuner       - Enable TEA575x tuner
+                          - 1 = MediaForte 256-PCS
+                          - 2 = MediaForte 256-PCPR
+                          - 3 = MediaForte 64-PCR  
+                          - High 16-bits are video (radio) device number + 1
+                          - example: 0x10002 (MediaForte 256-PCPR, device 1)
+
     Module supports up to 8 cards and autoprobe.
     
   Module snd-gusclassic
@@ -613,7 +627,7 @@
     model       - Use the given board model, one of the following:
 		  delta1010, dio2496, delta66, delta44, audiophile, delta410,
 		  delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
-		  dmx6fire, dsp24, dsp24_71, ez8
+		  dmx6fire, dsp24, dsp24_value, dsp24_71, ez8
     omni	- Omni I/O support for MidiMan M-Audio Delta44/66
     cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
                      in msec resolution, default value is 500 (0.5 sec)
@@ -631,7 +645,8 @@
 			* TerraTec Aureon Sky-5.1, Space-7.1
 
     model       - Use the given board model, one of the following:
-		  revo71, amp2000, prodigy71, aureon51, aureon71
+		  revo71, amp2000, prodigy71, aureon51, aureon71,
+		  k8x800
 
     Module supports up to 8 cards and autoprobe.
 
@@ -655,6 +670,8 @@
                      2 = swap headphone and master controls
                      3 = for AD1985, turn on OMS bit and use headphone
                      4 = for ALC65x, turn on the jack sense mode
+    buggy_irq      - Enable workaround for buggy interrupts on some
+                     motherboards (default off)
 
     Module supports autoprobe and multiple bus-master chips (max 8).
 
@@ -1102,6 +1119,16 @@
     pid             - Product ID for the device (optional)
 
     This module supports up to 8 cards, autoprobe and hotplugging.
+
+  Module snd-usb-usx2y
+  --------------------
+
+    Module for Tascam USB US-122, US-224 and US-428 devices.
+
+    This module supports up to 8 cards, autoprobe and hotplugging.
+
+    Note: you need to load the firmware via usx2yloader utility included
+          in alsa-tools and alsa-firmware packages.
 
   Module snd-via82xx
   ------------------
diff -Nru a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl	2004-03-08 21:43:17 -08:00
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl	2004-07-04 20:42:54 -07:00
@@ -47,7 +47,6 @@
      </sect1>
      <sect1><title>Memory Management Helpers</title>
 !Esound/core/memory.c
-!Iinclude/sound/sndmagic.h
 !Esound/core/memalloc.c
      </sect1>
   </chapter>
diff -Nru a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	2004-08-09 16:09:41 -07:00
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	2004-08-15 02:03:10 -07:00
@@ -18,8 +18,8 @@
       </affiliation>
      </author>
 
-     <date>Mar. 6, 2004</date>
-     <edition>0.3.1</edition>
+     <date>July 11, 2004</date>
+     <edition>0.3.3</edition>
 
     <abstract>
       <para>
@@ -395,7 +395,6 @@
   #include <linux/pci.h>
   #include <linux/slab.h>
   #include <sound/core.h>
-  #define SNDRV_GET_ID
   #include <sound/initval.h>
 
   // module parameters (see "Module Parameters")
@@ -411,10 +410,6 @@
           // "PCI Resource Managements"
   };
 
-  // this should be go into <sound/sndmagic.h>
-  // (see "Management of Cards and Components")
-  #define mychip_t_magic        0xa15a4501
-
   // chip-specific destructor
   // (see "PCI Resource Managements")
   static int snd_mychip_free(mychip_t *chip)
@@ -426,8 +421,7 @@
   // (see "Management of Cards and Components")
   static int snd_mychip_dev_free(snd_device_t *device)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                  device->device_data, return -ENXIO);
+          mychip_t *chip = device->device_data;
           return snd_mychip_free(chip);
   }
 
@@ -448,8 +442,8 @@
           // check PCI availability here
           // (see "PCI Resource Managements")
 
-          // allocate a chip-specific data with magic-alloc
-          chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);
+          // allocate a chip-specific data with zero filled
+          chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
           if (chip == NULL)
                   return -ENOMEM;
 
@@ -744,7 +738,6 @@
   #include <linux/pci.h>
   #include <linux/slab.h>
   #include <sound/core.h>
-  #define SNDRV_GET_ID
   #include <sound/initval.h>
 ]]>
           </programlisting>
@@ -906,13 +899,6 @@
       </para>
 
       <para>
-        You might have objections against such a typedef, but this
-      typedef is necessary if you use a <quote>magic-cast</quote>
-      (explained <link
-      linkend="card-management-chip-what-advantage"><citetitle>later</citetitle></link>). 
-      </para>
-
-      <para>
         In general, there are two ways to allocate the chip record.
       </para>
 
@@ -943,9 +929,8 @@
             </programlisting>
           </informalexample>
 
-          With this method, you don't have to allocate twice. But you
-        cannot use <quote>magic-cast</quote> for this record pointer,
-        instead. 
+          With this method, you don't have to allocate twice.
+          The record is released together with the card instance.
         </para>
       </section>
 
@@ -956,7 +941,7 @@
           After allocating a card instance via
           <function>snd_card_new()</function> (with
           <constant>NULL</constant> on the 4th arg), call
-          <function>snd_magic_kcalloc()</function>. 
+          <function>kcalloc()</function>. 
 
           <informalexample>
             <programlisting>
@@ -965,13 +950,10 @@
   mychip_t *chip;
   card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
   .....
-  chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);
+  chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 ]]>
             </programlisting>
           </informalexample>
-
-          Once when the record is allocated via snd_magic stuff, you
-        can use <quote>magic-cast</quote> for the void pointer. 
         </para>
 
         <para>
@@ -1003,21 +985,6 @@
         </para>
 
         <para>
-          Also, you need to define a magic-value for <type>mychip_t</type>.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  #define mychip_t_magic        0xa15a4501
-]]>
-            </programlisting>
-          </informalexample>
-	(the detail will be described in the
-	<link linkend="card-management-chip-what-advantage"><citetitle>
-	next</citetitle></link> subsection).
-	</para>
-
-        <para>
           Next, initialize the fields, and register this chip
           record as a low-level device with a specified
           <parameter>ops</parameter>, 
@@ -1045,8 +1012,7 @@
 <![CDATA[
   static int snd_mychip_dev_free(snd_device_t *device)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t, device->device_data,
-                                          return -ENXIO);
+          mychip_t *chip = device->device_data;
           return snd_mychip_free(chip);
   }
 ]]>
@@ -1056,126 +1022,6 @@
           where <function>snd_mychip_free()</function> is the real destructor.
         </para>
       </section>
-
-      <section id="card-management-chip-what-advantage">
-        <title>Not a magic but a logic</title>
-
-        <para>Now, you might have a question: What is the advantage of the
-        second method?  Obviously, it looks far more complicated.</para> 
-        <para>
-          As I wrote many times, the second method allows a
-        <quote>magic-cast</quote> for <type>mychip_t</type>. If you
-        have a void pointer (such as
-        pcm-&gt;private_data), the pointer type
-        is unknown at the compile time, and you cannot know even if a
-        wrong pointer type is passed. The compiler would accept
-        it. The magic-cast checks the pointer type at the runtime (and
-        whether it's a null pointer, too). Hence, the cast will be
-        much safer and good for debugging. 
-        </para>
-
-	<para>
-	As you have already seen, allocation with a magic-header can
-	be done via <function>snd_magic_kmalloc()</function> or
-	<function>snd_magic_kcalloc()</function>.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  mychip_t *chip;
-  chip = snd_magic_kmalloc(mychip_t, 0, GFP_KERNEL);
-  chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);
-]]>
-            </programlisting>
-          </informalexample>
-
-        The difference of these two functions is whether the area is
-	zero-cleared (<function>kcalloc</function>) or not
-	(<function>kmalloc</function>).
-	</para>
-
-	<para>
-	The first argument of the allocator is the type of the
-	record.  The magic-constant has to be defined for this type
-	beforehand.  In this case, we'll need to define
-	<constant>mychip_t_magic</constant>, for example, as already
-	seen,
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  #define mychip_t_magic        0xa15a4501
-]]>
-            </programlisting>
-          </informalexample>
-
-        The value is arbitrary but should be unique.
-        This is usually defined in
-        <filename>&lt;include/sndmagic.h&gt;</filename> or
-        <filename>&lt;include/amagic.h&gt;</filename> for alsa-driver tree,
-        but you may define it locally in the code at the early
-        development stage, since changing
-        <filename>sndmagic.h</filename> will lead to the recompilation
-        of the whole driver codes.
-        </para>
-
-	<para>
-	The second argument is the extra-data length.  It is usually
-        zero.  The third argument is the flags to be passed to kernel
-        memory allocator, <constant>GFP_XXX</constant>.  Normally,
-        <constant>GFP_KERNEL</constant> is passed.
-	</para>
-
-        <para>
-          For casting a pointer, use
-          <function>snd_magic_cast()</function> macro:
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  mychip_t *chip = snd_magic_cast(mychip_t, source_pointer, action);
-]]>
-            </programlisting>
-          </informalexample>
-
-        where <parameter>source_pointer</parameter> is the pointer to
-        be casted (e.g. pcm-&gt;private_data), and
-        <parameter>action</parameter> is the action to do if the cast
-        fails (e.g. return <constant>-EINVAL</constant>). 
-        </para>
-
-	<para>
-	For releasing the magic-allocated data, you need to call
-        <function>snd_magic_kfree()</function> function instead of
-        <function>kfree()</function>.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  snd_magic_kfree(chip);
-]]>
-            </programlisting>
-          </informalexample>
-	</para>
-
-	<para>
-	If you call <function>kfree()</function> for the
-	magic-allocated value, it will lead to memory leaks.
-	When the ALSA drivers are compiled with
-	<constant>CONFIG_SND_DEBUG_MEMORY</constant> kernel config (or
-	configured with <option>--with-debug=full</option>), the
-	non-matching free will be checked and you'll see warning
-	messages.
-	</para>
-
-        <para>
-          If you are 100% sure that your code is bug-free, you can
-          compile the driver without
-          <constant>CONFIG_SND_DEBUG_MEMORY</constant> kernel config,
-          so that the magic-allocator and the magic-cast will be
-          replaced to the normal kmalloc and cast.
-        </para>
-      </section>
     </section>
 
     <section id="card-management-registration">
@@ -1238,8 +1084,6 @@
           struct pci_dev *pci;
 
           unsigned long port;
-          struct resource *res_port;
-
           int irq;
   };
 
@@ -1248,16 +1092,13 @@
           // disable hardware here if any
           // (not implemented in this document)
 
-          // release the i/o port
-          if (chip->res_port) {
-                  release_resource(chip->res_port);
-                  kfree_nocheck(chip->res_port);
-          }
           // release the irq
           if (chip->irq >= 0)
                   free_irq(chip->irq, (void *)chip);
+          // release the i/o ports
+          pci_release_regions(chip->pci);
           // release the data
-          snd_magic_kfree(chip);
+          kfree(chip);
           return 0;
   }
 
@@ -1283,7 +1124,7 @@
                   return -ENXIO;
           }
 
-          chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);
+          chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
           if (chip == NULL)
                   return -ENOMEM;
 
@@ -1293,18 +1134,16 @@
           chip->irq = -1;
 
           // (1) PCI resource allocation
-          chip->port = pci_resource_start(pci, 0);
-          if ((chip->res_port = request_region(chip->port, 8,
-                                                 "My Chip")) == NULL) { 
-                  snd_mychip_free(chip);
-                  printk(KERN_ERR "cannot allocate the port\n");
-                  return -EBUSY;
+          if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+                  kfree(chip);
+                  return err;
           }
+          chip->port = pci_resource_start(pci, 0);
           if (request_irq(pci->irq, snd_mychip_interrupt,
                           SA_INTERRUPT|SA_SHIRQ, "My Chip",
                           (void *)chip)) {
+                  printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
                   snd_mychip_free(chip);
-                  printk(KERN_ERR "cannot grab irq\n");
                   return -EBUSY;
           }
           chip->irq = pci->irq;
@@ -1420,8 +1259,6 @@
           snd_card_t *card;
 
           unsigned long port;
-          struct resource *res_port;
-
           int irq;
   };
 ]]>
@@ -1436,7 +1273,7 @@
       need to initialize this number as -1 before actual allocation,
       since irq 0 is valid. The port address and its resource pointer
       can be initialized as null by
-      <function>snd_magic_kcalloc()</function> automatically, so you
+      <function>kcalloc()</function> automatically, so you
       don't have to take care of resetting them. 
       </para>
 
@@ -1446,14 +1283,11 @@
         <informalexample>
           <programlisting>
 <![CDATA[
-  chip->port = pci_resource_start(pci, 0);
-  if ((chip->res_port = request_region(chip->port, 8,
-                                       "My Chip")) == NULL) { 
-          printk(KERN_ERR "cannot allocate the port 0x%lx\n",
-                 chip->port);
-          snd_mychip_free(chip);
-          return -EBUSY;
+  if ((err = pci_request_regions(pci, "My Chip")) < 0) { 
+          kfree(chip);
+          return err;
   }
+  chip->port = pci_resource_start(pci, 0);
 ]]>
           </programlisting>
         </informalexample>
@@ -1477,8 +1311,8 @@
   if (request_irq(pci->irq, snd_mychip_interrupt,
                   SA_INTERRUPT|SA_SHIRQ, "My Chip",
                   (void *)chip)) {
-          snd_mychip_free(chip);
           printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+          snd_mychip_free(chip);
           return -EBUSY;
   }
   chip->irq = pci->irq;
@@ -1517,16 +1351,13 @@
   static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
                                           struct pt_regs *regs)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return);
+          mychip_t *chip = dev_id;
           ....
           return IRQ_HANDLED;
   }
 ]]>
           </programlisting>
         </informalexample>
-
-        Again the magic-cast is used here to get the correct pointer
-      from the second argument. 
       </para>
 
       <para>
@@ -1538,7 +1369,45 @@
 
       <para>
         For releasing the resources, <quote>check-and-release</quote>
-        method is a safer way. For the i/o port, do like this: 
+        method is a safer way. For the interrupt, do like this: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  if (chip->irq >= 0)
+          free_irq(chip->irq, (void *)chip);
+]]>
+          </programlisting>
+        </informalexample>
+
+        Since the irq number can start from 0, you should initialize
+        chip-&gt;irq with a negative value (e.g. -1), so that you can
+        check the validity of the irq number as above.
+      </para>
+
+      <para>
+        When you requested I/O ports or memory regions via
+	<function>pci_request_region()</function> or
+	<function>pci_request_regions()</function> like this example,
+	release the resource(s) using the corresponding function,
+	<function>pci_release_region()</function> or
+	<function>pci_release_regions()</function>.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  pci_release_regions(chip->pci);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+	When you requested manually via <function>request_region()</function>
+	or <function>request_mem_region</function>, you can release it via
+	<function>release_resource()</function>.  Suppose that you keep
+	the resource pointer returned from <function>request_region()</function>
+	in chip-&gt;res_port, the release procedure looks like below:
 
         <informalexample>
           <programlisting>
@@ -1550,10 +1419,8 @@
 ]]>
           </programlisting>
         </informalexample>
-      </para>
 
-      <para>
-        As you can see, the i/o resource pointer is also to be freed
+      As you can see, the resource pointer is also to be freed
       via <function>kfree_nocheck()</function> after
       <function>release_resource()</function> is called. You
       cannot use <function>kfree()</function> here, because on ALSA,
@@ -1567,35 +1434,19 @@
       </para>
 
       <para>
-        For releasing the interrupt, do like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if (chip->irq >= 0)
-          free_irq(chip->irq, (void *)chip);
-]]>
-          </programlisting>
-        </informalexample>
-
         And finally, release the chip-specific record.
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  snd_magic_kfree(chip);
+  kfree(chip);
 ]]>
           </programlisting>
         </informalexample>
       </para>
 
       <para>
-        The chip instance is freed via
-      <function>snd_magic_kfree()</function>. Please use this function
-      for the object allocated by
-      <function>snd_magic_kmalloc()</function>. If you free it with
-      <function>kfree()</function>, it won't work properly and will
-      result in the memory leak. Also, again, remember that you cannot
+      Again, remember that you cannot
       set <parameter>__devexit</parameter> prefix for this destructor. 
       </para>
 
@@ -1629,7 +1480,6 @@
           ....
           unsigned long iobase_phys;
           unsigned long iobase_virt;
-          struct resource *res_iobase;
   };
 ]]>
           </programlisting>
@@ -1640,15 +1490,14 @@
         <informalexample>
           <programlisting>
 <![CDATA[
+  if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+          kfree(chip);
+          return err;
+  }
   chip->iobase_phys = pci_resource_start(pci, 0);
   chip->iobase_virt = (unsigned long)
-                      ioremap_nocache(chip->iobase_phys, 512);
-  if ((chip->res_port = request_mem_region(chip->iobase_phys, 512,
-                                           "My Chip")) == NULL) {
-          printk(KERN_ERR "cannot allocate the memory region\n");
-          snd_mychip_free(chip);
-          return -EBUSY;
-  }
+                      ioremap_nocache(chip->iobase_phys,
+                                      pci_resource_len(pci, 0));
 ]]>
           </programlisting>
         </informalexample>
@@ -1663,10 +1512,8 @@
           ....
           if (chip->iobase_virt)
                   iounmap((void *)chip->iobase_virt);
-          if (chip->res_iobase) {
-                  release_resource(chip->res_iobase);
-                  kfree_nocheck(chip->res_iobase);
-          }
+          ....
+          pci_release_regions(chip->pci);
           ....
   }
 ]]>
@@ -1857,9 +1704,6 @@
   #include <sound/pcm.h>
   ....
 
-  #define chip_t mychip_t
-  ....
-
   /* hardware definition */
   static snd_pcm_hardware_t snd_mychip_playback_hw = {
           .info = (SNDRV_PCM_INFO_MMAP |
@@ -2224,8 +2068,7 @@
 <![CDATA[
   static void mychip_pcm_free(snd_pcm_t *pcm)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                                    pcm->private_data, return);
+          mychip_t *chip = snd_pcm_chip(pcm);
           // free your own data
           kfree(chip->my_private_pcm_data);
           // do what you like else...
@@ -2653,8 +2496,11 @@
 	done in
 	<link linkend="pcm-interface-operators-open-callback"><citetitle>
 	the open callback</citetitle></link>.
-        Since it's a void pointer, you should use magic-kmalloc and
-	magic-cast for such an object. 
+	Don't mix this with <constant>pcm-&gt;private_data</constant>.
+	The <constant>pcm-&gt;private_data</constant> usually points the
+	chip instance assigned statically at the creation of PCM, while the 
+	<constant>runtime-&gt;private_data</constant> points a dynamic
+	data created at the PCM open callback.
 
           <informalexample>
             <programlisting>
@@ -2663,7 +2509,7 @@
   {
           my_pcm_data_t *data;
           ....
-          data = snd_magic_kmalloc(my_pcm_data_t, 0, GFP_KERNEL);
+          data = kmalloc(sizeof(*data), GFP_KERNEL);
           substream->runtime->private_data = data;
           ....
   }
@@ -2710,8 +2556,6 @@
         <informalexample>
           <programlisting>
 <![CDATA[
-  #define chip_t mychip_t
-
   int xxx() {
           mychip_t *chip = snd_pcm_substream_chip(substream);
           ....
@@ -2719,13 +2563,14 @@
 ]]>
           </programlisting>
         </informalexample>
-      </para>
 
-      <para>
-        It's expanded with a magic-cast, so the cast-error is
-      automatically checked. You should define <type>chip_t</type> at
-      the beginning of the code, since this will be referred in many
-      places of pcm and control interfaces. 
+	The macro reads <constant>substream-&gt;private_data</constant>,
+	which is a copy of <constant>pcm-&gt;private_data</constant>.
+	You can override the former if you need to assign different data
+	records per PCM substream.  For example, cmi8330 driver assigns
+	different private_data for playback and capture directions,
+	because it uses two different codecs (SB- and AD-compatible) for
+	different directions.
       </para>
 
       <section id="pcm-interface-operators-open-callback">
@@ -2803,7 +2648,7 @@
   static int snd_xxx_close(snd_pcm_substream_t *substream)
   {
           ....
-          snd_magic_kfree(substream->runtime->private_data);
+          kfree(substream->runtime->private_data);
           ....
   }
 ]]>
@@ -2887,10 +2732,10 @@
         <para>
           Another note is that this callback is non-atomic
         (schedulable). This is important, because the
-        <structfield>prepare</structfield> callback 
+        <structfield>trigger</structfield> callback 
         is atomic (non-schedulable). That is, mutex or any
-        schedule-related functions are available only in
-        <structfield>hw_params</structfield> callback. 
+        schedule-related functions are not available in
+        <structfield>trigger</structfield> callback.
 	Please see the subsection
 	<link linkend="pcm-interface-atomicity"><citetitle>
 	Atomicity</citetitle></link> for details.
@@ -2956,7 +2801,8 @@
         </para>
 
         <para>
-          As mentioned above, this callback is atomic.
+	Note that this callback became non-atomic since the recent version.
+	You can use schedule-related fucntions safely in this callback now.
         </para>
 
         <para>
@@ -3041,7 +2887,12 @@
         </para>
 
         <para>
-          This callback is also atomic.
+          As mentioned, this callback is atomic.  You cannot call
+	  the function going to sleep.
+	  The trigger callback should be as minimal as possible,
+	  just really triggering the DMA.  The other stuff should be
+	  initialized hw_params and prepare callbacks properly
+	  beforehand.
         </para>
       </section>
 
@@ -3176,7 +3027,7 @@
   static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
                                           struct pt_regs *regs)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return);
+          mychip_t *chip = dev_id;
           spin_lock(&chip->lock);
           ....
           if (pcm_irq_invoked(chip)) {
@@ -3220,7 +3071,7 @@
   static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
                                           struct pt_regs *regs)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return);
+          mychip_t *chip = dev_id;
           spin_lock(&chip->lock);
           ....
           if (pcm_irq_invoked(chip)) {
@@ -3287,7 +3138,7 @@
       <para>
       As already seen, some pcm callbacks are atomic and some are
       not.  For example, <parameter>hw_params</parameter> callback is
-      non-atomic, while <parameter>prepare</parameter> callback is
+      non-atomic, while <parameter>trigger</parameter> callback is
       atomic.  This means, the latter is called already in a spinlock
       held by the PCM middle layer. Please take this atomicity into
       account when you use a spinlock or a semaphore in the callbacks.
@@ -3298,7 +3149,7 @@
       <function>schedule</function> or go to
       <function>sleep</function>.  The semaphore and mutex do sleep,
       and hence they cannot be used inside the atomic callbacks
-      (e.g. <parameter>prepare</parameter> callback).
+      (e.g. <parameter>trigger</parameter> callback).
       For taking a certain delay in such a callback, please use
       <function>udelay()</function> or <function>mdelay()</function>.
       </para>
@@ -3325,7 +3176,7 @@
   static unsigned int rates[] =
           {4000, 10000, 22050, 44100};
   static snd_pcm_hw_constraint_list_t constraints_rates = {
-          .count = sizeof(rates) / sizeof(rates[0]),
+          .count = ARRAY_SIZE(rates),
           .list = rates,
           .mask = 0,
   };
@@ -3988,8 +3839,7 @@
   static unsigned short snd_mychip_ac97_read(ac97_t *ac97,
                                              unsigned short reg)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                                   ac97->private_data, return 0);
+          mychip_t *chip = ac97->private_data;
           ....
           // read a register value here from the codec
           return the_register_value;
@@ -3998,26 +3848,26 @@
   static void snd_mychip_ac97_write(ac97_t *ac97,
                                    unsigned short reg, unsigned short val)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                                   ac97->private_data, return 0);
+          mychip_t *chip = ac97->private_data;
           ....
           // write the given register value to the codec
   }
 
   static int snd_mychip_ac97(mychip_t *chip)
   {
-          ac97_bus_t bus, *pbus;
-          ac97_t ac97;
+          ac97_bus_t *bus;
+          ac97_template_t ac97;
           int err;
+          static ac97_bus_ops_t ops = {
+                  .write = snd_mychip_ac97_write,
+                  .read = snd_mychip_ac97_read,
+          };
 
-          memset(&bus, 0, sizeof(bus));
-          bus.write = snd_mychip_ac97_write;
-          bus.read = snd_mychip_ac97_read;
-          if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+          if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
                   return err;
           memset(&ac97, 0, sizeof(ac97));
           ac97.private_data = chip;
-          return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
+          return snd_ac97_mixer(bus, &ac97, &chip->ac97);
   }
 
 ]]>
@@ -4030,18 +3880,18 @@
       <title>Constructor</title>
       <para>
         For creating an ac97 instance, first call <function>snd_ac97_bus</function>
-      with <type>ac97_bus_t</type> record including callback functions.
+      with an <type>ac97_bus_ops_t</type> record with callback functions.
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  ac97_bus_t bus, *pbus;
-  int err;
+  ac97_bus_t *bus;
+  static ac97_bus_ops_t ops = {
+        .write = snd_mychip_ac97_write,
+        .read = snd_mychip_ac97_read,
+  };
 
-  memset(&bus, 0, sizeof(bus));
-  bus.write = snd_mychip_ac97_write;
-  bus.read = snd_mychip_ac97_read;
-  snd_ac97_bus(card, &bus, &pbus);
+  snd_ac97_bus(card, 0, &ops, NULL, &pbus);
 ]]>
           </programlisting>
         </informalexample>
@@ -4050,13 +3900,13 @@
       </para>
 
       <para>
-      And then call <function>snd_ac97_mixer()</function> with an <type>ac97_t</type>
+      And then call <function>snd_ac97_mixer()</function> with an <type>ac97_template_t</type>
       record together with the bus pointer created above.
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  ac97_t ac97;
+  ac97_template_t ac97;
   int err;
 
   memset(&ac97, 0, sizeof(ac97));
@@ -4096,8 +3946,7 @@
   static unsigned short snd_mychip_ac97_read(ac97_t *ac97,
                                              unsigned short reg)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                                   ac97->private_data, return 0);
+          mychip_t *chip = ac97->private_data;
           ....
           return the_register_value;
   }
@@ -4241,7 +4090,7 @@
       <para>
         On some chip, the clock of the codec isn't 48000 but using a
       PCI clock (to save a quartz!). In this case, change the field
-      ac97-&gt;clock to the corresponding
+      bus-&gt;clock to the corresponding
       value. For example, intel8x0 
       and es1968 drivers have the auto-measurement function of the
       clock. 
@@ -4375,7 +4224,7 @@
           <programlisting>
 <![CDATA[
   mpu401_t *mpu;
-  mpu = snd_magic_cast(mpu401_t, rmidi->private_data, );
+  mpu = rmidi->private_data;
 ]]>
           </programlisting>
         </informalexample>
@@ -4546,16 +4395,15 @@
 
       <para>
         You can then pass any pointer value to the
-        <parameter>private_data</parameter>. Again, it should be a
-        magic-allocated record, so that the cast can be checked more
-        safely. If you assign a private data, you should define the
+        <parameter>private_data</parameter>.
+        If you assign a private data, you should define the
         destructor, too. The destructor function is set to
         <structfield>private_free</structfield> field.  
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  mydata_t *p = snd_magic_kmalloc(mydata_t, 0, GFP_KERNEL);
+  mydata_t *p = kmalloc(sizeof(*p), GFP_KERNEL);
   hw->private_data = p;
   hw->private_free = mydata_free;
 ]]>
@@ -4569,9 +4417,8 @@
 <![CDATA[
   static void mydata_free(snd_hwdep_t *hw)
   {
-          mydata_t *p = snd_magic_cast(mydata_csp_t,
-                                       hw->private_data, return);
-          snd_magic_kfree(p);
+          mydata_t *p = hw->private_data;
+          kfree(p);
   }
 ]]>
           </programlisting>
@@ -5097,8 +4944,7 @@
   static void my_proc_read(snd_info_entry_t *entry,
                            snd_info_buffer_t *buffer)
   {
-          chip_t *cm = snd_magic_cast(mychip_t,
-                                  entry->private_data, return);
+          chip_t *chip = entry->private_data;
 
           snd_iprintf(buffer, "This is my chip!\n");
           snd_iprintf(buffer, "Port = %ld\n", chip->port);
@@ -5267,8 +5113,7 @@
   static int mychip_suspend(snd_card_t *card, unsigned int state)
   {
           // (1)
-          mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data,
-                                          return -ENXIO);
+          mychip_t *chip = card->pm_private_data;
           // (2)
           snd_pcm_suspend_all(chip->pcm);
           // (3)
@@ -5310,8 +5155,7 @@
   static void mychip_resume(mychip_t *chip)
   {
           // (1)
-          mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data,
-                                          return -ENXIO);
+          mychip_t *chip = card->pm_private_data;
           // (2)
           pci_enable_device(chip->pci);
           // (3)
@@ -5428,19 +5272,7 @@
       The module parameters must be declared with the standard
     <function>module_param()()</function>,
     <function>module_param_array()()</function> and
-    <function>MODULE_PARM_DESC()</function> macros. The ALSA provides
-    an additional macro, <function>MODULE_PARM_SYNTAX()</function>,
-    for describing its syntax. The strings will be written to
-    <filename>/lib/modules/XXX/modules.generic_string</filename>
-    file. 
-    </para>
-
-    <para>
-      For convenience, the typical string arguments given to
-    <function>MODULE_PARM_SYNTAX()</function> are defined in
-    <filename>&lt;sound/initval.h&gt;</filename>, such as
-    <constant>SNDRV_ID_DESC</constant> or
-    <constant>SNDRV_ENABLED</constant>.
+    <function>MODULE_PARM_DESC()</function> macros.
     </para>
 
     <para>
@@ -5454,13 +5286,10 @@
   static int boot_devs;
   module_param_array(index, int, boot_devs, 0444);
   MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-  MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
   module_param_array(id, charp, boot_devs, 0444);
   MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-  MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
   module_param_array(enable, bool, boot_devs, 0444);
   MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-  MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 ]]>
         </programlisting>
       </informalexample>
@@ -5479,9 +5308,8 @@
         <programlisting>
 <![CDATA[
   MODULE_DESCRIPTION("My Chip");
-  MODULE_CLASSES("{sound}");
   MODULE_LICENSE("GPL");
-  MODULE_DEVICES("{{Vendor,My Chip Name}}");
+  MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}");
 ]]>
         </programlisting>
       </informalexample>
@@ -5636,14 +5464,14 @@
   SND_TOPDIR=../..
   endif
 
-  include $(TOPDIR)/toplevel.config
-  include $(TOPDIR)/Makefile.conf
+  include $(SND_TOPDIR)/toplevel.config
+  include $(SND_TOPDIR)/Makefile.conf
 
   snd-xyz-objs := xyz.o abc.o def.o
 
   obj-$(CONFIG_SND_XYZ) += snd-xyz.o
 
-  include $(TOPDIR)/Rules.make
+  include $(SND_TOPDIR)/Rules.make
 ]]>
         </programlisting>
       </example>
diff -Nru a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
--- a/Documentation/sysctl/kernel.txt	2004-02-03 21:30:55 -08:00
+++ b/Documentation/sysctl/kernel.txt	2004-08-24 02:09:06 -07:00
@@ -23,7 +23,6 @@
 - dentry-state
 - domainname
 - hostname
-- htab-reclaim                [ PPC only ]
 - hotplug
 - java-appletviewer           [ binfmt_java, obsolete ]
 - java-interpreter            [ binfmt_java, obsolete ]
@@ -54,7 +53,6 @@
 - tainted
 - threads-max
 - version
-- zero-paged                  [ PPC only ]
 
 ==============================================================
 
@@ -145,14 +143,6 @@
 
 ==============================================================
 
-htab-reclaim: (PPC only)
-
-Setting this to a non-zero value, the PowerPC htab
-(see Documentation/powerpc/ppc_htab.txt) is pruned
-each time the system hits the idle loop.
- 
-==============================================================
-
 hotplug:
 
 Path for the hotplug policy agent.
@@ -322,11 +312,3 @@
       Set by modutils >= 2.4.9 and module-init-tools.
   4 - Unsafe SMP processors: SMP with CPUs not designed for SMP.
 
-==============================================================
-
-zero-paged: (PPC only)
-
-When enabled (non-zero), Linux-PPC will pre-zero pages in
-the idle loop, possibly speeding up get_free_pages. Since
-this only affects what the idle loop is doing, you should
-enable this and see if anything changes.
diff -Nru a/Documentation/usb/philips.txt b/Documentation/usb/philips.txt
--- a/Documentation/usb/philips.txt	2004-05-12 06:54:07 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,236 +0,0 @@
-This file contains some additional information for the Philips and OEM webcams.
-E-mail: webcam@smcc.demon.nl                        Last updated: 2004-01-19
-Site: http://www.smcc.demon.nl/webcam/
-
-As of this moment, the following cameras are supported:
- * Philips PCA645
- * Philips PCA646
- * Philips PCVC675
- * Philips PCVC680
- * Philips PCVC690
- * Philips PCVC720/40
- * Philips PCVC730
- * Philips PCVC740
- * Philips PCVC750
- * Askey VC010
- * Creative Labs Webcam 5
- * Creative Labs Webcam Pro Ex
- * Logitech QuickCam 3000 Pro
- * Logitech QuickCam 4000 Pro
- * Logitech QuickCam Notebook Pro
- * Logitech QuickCam Zoom
- * Logitech QuickCam Orbit
- * Logitech QuickCam Sphere
- * Samsung MPC-C10
- * Samsung MPC-C30
- * Sotec Afina Eye
- * AME CU-001
- * Visionite VCS-UM100
- * Visionite VCS-UC300
-
-The main webpage for the Philips driver is at the address above. It contains
-a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
-contains decompression routines that allow you to use higher image sizes and
-framerates; in addition the webcam uses less bandwidth on the USB bus (handy
-if you want to run more than 1 camera simultaneously). These routines fall
-under a NDA, and may therefor not be distributed as source; however, its use
-is completely optional.
-
-You can build this code either into your kernel, or as a module. I recommend
-the latter, since it makes troubleshooting a lot easier. The built-in
-microphone is supported through the USB Audio class.
-
-When you load the module you can set some default settings for the
-camera; some programs depend on a particular image-size or -format and
-don't know how to set it properly in the driver. The options are:
-
-size
-   Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
-   'vga', for an image size of resp. 128x96, 160x120, 176x144,
-   320x240, 352x288 and 640x480 (of course, only for those cameras that 
-   support these resolutions).
-
-fps
-   Specifies the desired framerate. Is an integer in the range of 4-30.
-
-fbufs
-   This paramter specifies the number of internal buffers to use for storing 
-   frames from the cam. This will help if the process that reads images from 
-   the cam is a bit slow or momentarely busy. However, on slow machines it 
-   only introduces lag, so choose carefully. The default is 3, which is 
-   reasonable. You can set it between 2 and 5.
-
-mbufs
-   This is an integer between 1 and 10. It will tell the module the number of
-   buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
-   The default is 2, which is adequate for most applications (double
-   buffering).
-      
-   Should you experience a lot of 'Dumping frame...' messages during
-   grabbing with a tool that uses mmap(), you might want to increase if. 
-   However, it doesn't really buffer images, it just gives you a bit more
-   slack when your program is behind. But you need a multi-threaded or
-   forked program to really take advantage of these buffers.
-
-   The absolute maximum is 10, but don't set it too high!  Every buffer takes
-   up 460 KB of RAM, so unless you have a lot of memory setting this to
-   something more than 4 is an absolute waste.  This memory is only
-   allocated during open(), so nothing is wasted when the camera is not in
-   use.
-
-power_save
-   When power_save is enabled (set to 1), the module will try to shut down
-   the cam on close() and re-activate on open(). This will save power and
-   turn off the LED. Not all cameras support this though (the 645 and 646
-   don't have power saving at all), and some models don't work either (they
-   will shut down, but never wake up). Consider this experimental. By
-   default this option is disabled.
-
-compression (only useful with the plugin)
-   With this option you can control the compression factor that the camera
-   uses to squeeze the image through the USB bus. You can set the 
-   parameter between 0 and 3:
-     0 = prefer uncompressed images; if the requested mode is not available
-         in an uncompressed format, the driver will silently switch to low
-         compression.
-     1 = low compression.
-     2 = medium compression.
-     3 = high compression.
-      
-   High compression takes less bandwidth of course, but it could also
-   introduce some unwanted artefacts. The default is 2, medium compression.
-   See the FAQ on the website for an overview of which modes require
-   compression.
-
-   The compression parameter does not apply to the 645 and 646 cameras
-   and OEM models derived from those (only a few). Most cams honour this
-   parameter.
-
-leds
-   This settings takes 2 integers, that define the on/off time for the LED
-   (in milliseconds). One of the interesting things that you can do with
-   this is let the LED blink while the camera is in use. This:
-
-     leds=500,500
-      
-   will blink the LED once every second. But with:
-
-     leds=0,0
-
-   the LED never goes on, making it suitable for silent surveillance.
-
-   By default the camera's LED is on solid while in use, and turned off
-   when the camera is not used anymore.
-
-   This parameter works only with the ToUCam range of cameras (720, 730, 740,
-   750) and OEMs. For other cameras this command is silently ignored, and 
-   the LED cannot be controlled.
-
-   Finally: this parameters does not take effect UNTIL the first time you
-   open the camera device. Until then, the LED remains on.
-
-dev_hint
-   A long standing problem with USB devices is their dynamic nature: you
-   never know what device a camera gets assigned; it depends on module load
-   order, the hub configuration, the order in which devices are plugged in,
-   and the phase of the moon (i.e. it can be random). With this option you
-   can give the driver a hint as to what video device node (/dev/videoX) it
-   should use with a specific camera. This is also handy if you have two
-   cameras of the same model.
-
-   A camera is specified by its type (the number from the camera model,
-   like PCA645, PCVC750VC, etc) and optionally the serial number (visible
-   in /proc/bus/usb/devices). A hint consists of a string with the following
-   format:
-
-      [type[.serialnumber]:]node
-      
-   The square brackets mean that both the type and the serialnumber are
-   optional, but a serialnumber cannot be specified without a type (which
-   would be rather pointless). The serialnumber is separated from the type
-   by a '.'; the node number by a ':'.
-   
-   This somewhat cryptic syntax is best explained by a few examples:
-
-     dev_hint=3,5              The first detected cam gets assigned
-                               /dev/video3, the second /dev/video5. Any
-                               other cameras will get the first free 
-                               available slot (see below).
-
-     dev_hint=645:1,680:2      The PCA645 camera will get /dev/video1,
-                               and a PCVC680 /dev/video2.
-                               
-     dev_hint=645.0123:3,645.4567:0	The PCA645 camera with serialnumber 
-                                        0123 goes to /dev/video3, the same
-                                        camera model with the 4567 serial
-                                        gets /dev/video0.
-
-     dev_hint=750:1,4,5,6       The PCVC750 camera will get /dev/video1, the 
-                                next 3 Philips cams will use /dev/video4 
-                                through /dev/video6.
-
-   Some points worth knowing:
-   - Serialnumbers are case sensitive and must be written full, including 
-     leading zeroes (it's treated as a string).
-   - If a device node is already occupied, registration will fail and 
-     the webcam is not available.
-   - You can have up to 64 video devices; be sure to make enough device
-     nodes in /dev if you want to spread the numbers (this does not apply
-     to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA).
-   - If a camera does not match any dev_hint, it will simply get assigned
-     the first available device node, just as it used to be.
-
-trace
-   In order to better detect problems, it is now possible to turn on a
-   'trace' of some of the calls the module makes; it logs all items in your
-   kernel log at debug level.
-
-   The trace variable is a bitmask; each bit represents a certain feature.
-   If you want to trace something, look up the bit value(s) in the table 
-   below, add the values together and supply that to the trace variable.
-
-   Value  Value   Description					   Default
-   (dec)  (hex)
-       1    0x1   Module initialization; this will log messages       On
-                  while loading and unloading the module
-
-       2    0x2   probe() and disconnect() traces                     On
-
-       4    0x4   Trace open() and close() calls                      Off
-
-       8    0x8   read(), mmap() and associated ioctl() calls         Off
-
-      16   0x10   Memory allocation of buffers, etc.                  Off
-
-      32   0x20   Showing underflow, overflow and Dumping frame       On
-                  messages
-
-      64   0x40   Show viewport and image sizes                       Off
-
-     128   0x80   PWCX debugging                                      Off
-
-   For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
-   so you would supply trace=12 during insmod or modprobe. If
-   you want to turn the initialization and probing tracing off, set trace=0.
-   The default value for trace is 35 (0x23).
-
-
-
-Example:
-     
-     # modprobe pwc size=cif fps=15 power_save=1
-
-The fbufs, mbufs and trace parameters are global and apply to all connected
-cameras. Each camera has its own set of buffers.
-
-size and fps only specify defaults when you open() the device; this is to
-accommodate some tools that don't set the size. You can change these
-settings after open() with the Video4Linux ioctl() calls. The default of
-defaults is QCIF size at 10 fps.
-
-The compression parameter is semiglobal; it sets the initial compression
-preference for all camera's, but this parameter can be set per camera with
-the VIDIOCPWCSCQUAL ioctl() call.
-
-All parameters are optional.
-
diff -Nru a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt
--- a/Documentation/usb/sn9c102.txt	2004-08-03 00:57:11 -07:00
+++ b/Documentation/usb/sn9c102.txt	2004-08-11 19:25:22 -07:00
@@ -14,10 +14,10 @@
 4.  Module dependencies
 5.  Module loading
 6.  Module parameters
-7.  Device control through "sysfs"
+7.  Optional device control through "sysfs"
 8.  Supported devices
 9.  How to add support for new image sensors
-10. Note for V4L2 developers
+10. Notes for V4L2 application developers
 11. Contact information
 12. Credits
 
@@ -148,8 +148,8 @@
 -------------------------------------------------------------------------------
 
 
-7. Device control through "sysfs"
-=================================
+7. Optional device control through "sysfs"
+==========================================
 It is possible to read and write both the SN9C10[12] and the image sensor
 registers by using the "sysfs" filesystem interface.
 
@@ -206,7 +206,7 @@
 0xc45      0x6029
 0xc45      0x602a
 0xc45      0x602c
-0xc45      0x8001
+0xc45      0x6030
 
 The list above does NOT imply that all those devices work with this driver: up
 until now only the ones that mount the following image sensors are supported.
@@ -242,19 +242,27 @@
 MI03 (VGA), OV7620 (VGA).
 
 
-10. Note for V4L2 developers
-============================
+10. Notes for V4L2 application developers
+=========================================
 This driver follows the V4L2 API specifications. In particular, it enforces two
 rules:
 
-1) Exactly one I/O method, either "mmap" or "read", is associated with each
+- exactly one I/O method, either "mmap" or "read", is associated with each
 file descriptor. Once it is selected, the application must close and reopen the
-device to switch to the other I/O method.
+device to switch to the other I/O method;
 
-2) Previously mapped buffer memory must always be unmapped before calling any
-of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. In case,
-the same number of buffers as before will be allocated again to match the size
-of the new video frames, so you have to map them again before any I/O attempts.
+- previously mapped buffer memory must always be unmapped before calling any
+of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. The same
+number of buffers as before will be allocated again to match the size of the
+new video frames, so you have to map them again before any I/O attempts.
+
+Consistently with the hardware limits, this driver also supports image
+downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
+However the V4L2 API specifications don't correctly define how the scaling
+factor can be choosen arbitrarily by the "negotiation" of the "source" and
+"target" rectangles. To work around this flaw, we have added the convention
+that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
+scaling factor is restored to 1.
 
 
 11. Contact information
diff -Nru a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
--- a/Documentation/x86_64/boot-options.txt	2004-03-20 11:16:19 -08:00
+++ b/Documentation/x86_64/boot-options.txt	2004-08-24 02:08:31 -07:00
@@ -136,17 +136,25 @@
 
 IOMMU
 
-  iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,soft]
+ iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
+         [,forcesac][,fullflush][,nomerge][,noaperture]
    size  set size of iommu (in bytes)
    noagp don't initialize the AGP driver and use full aperture.
    off   don't use the IOMMU
    leak  turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
    memaper[=order] allocate an own aperture over RAM with size 32MB^order.
    noforce don't force IOMMU usage. Default.
-   force  Force IOMMU
-   soft   Use software bounce buffering for non 32bit IO. Default on Intel
-          machines. 
+   force  Force IOMMU.
+   merge  Do SG merging. Implies force (experimental)
+   nomerge Don't do SG merging.
+   forcesac For SAC mode for masks <40bits  (experimental)
+   fullflush Flush IOMMU on each allocation (default)
+   nofullflush Don't use IOMMU fullflush
+   allowed  overwrite iommu off workarounds for specific chipsets.
+   soft	 Use software bounce buffering (default for Intel machines)
+   noaperture Don't touch the aperture for AGP.
 
-  swiotlb=pages
+  swiotlb=pages[,force]
 
-  Prereserve that many 4K pages for the software IO bounce buffering.
+  pages  Prereserve that many 128K pages for the software IO bounce buffering.
+  force  Force all IO through the software TLB.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2004-08-23 14:24:13 -07:00
+++ b/MAINTAINERS	2004-08-28 11:46:04 -07:00
@@ -169,7 +169,7 @@
 P:	Robert Siemer
 M:	Robert.Siemer@gmx.de
 L:	linux-sound@vger.kernel.org
-W:	http://www.uni-karlsruhe.de/~Robert.Siemer/Private/
+W:	http://www.stud.uni-karlsruhe.de/~uh1b/
 S:	Maintained
 
 ACP/MWAVE MODEM
@@ -195,8 +195,14 @@
 
 AD1816 SOUND DRIVER
 P:	Thorsten Knabe
-W:	http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
-W:	http://www.tu-darmstadt.de/~tek01/projects/linux.html
+M:	Thorsten Knabe <linux@thorsten-knabe.de>
+W:	http://linux.thorsten-knabe.de
+S:	Maintained
+
+ADM1025 HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
 S:	Maintained
 
 ADT746X FAN DRIVER
@@ -563,7 +569,7 @@
 P:	James Morris
 M:	jmorris@redhat.com
 P:	David S. Miller
-M:	davem@redhat.com
+M:	davem@davemloft.net
 W	http://samba.org/~jamesm/crypto/
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
@@ -621,6 +627,8 @@
 P:	Kurt Garloff
 M:	garloff@suse.de
 W:	http://www.garloff.de/kurt/linux/dc390/
+P:	Guennadi Liakhovetski
+M:	g.liakhovetski@gmx.de
 S:	Maintained
 
 DECnet NETWORK LAYER
@@ -648,8 +656,9 @@
 S:	Maintained
 
 DEVICE NUMBER REGISTRY
-P:	John Cagle
+P:	Torben Mathiasen
 M:	device@lanana.org
+W:	http://lanana.org/docs/device-list/index.html
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
@@ -762,8 +771,8 @@
 S:	Maintained
 
 EMU10K1 SOUND DRIVER
-P:	Rui Sousa	
-M:	rui.p.m.sousa@clix.pt	
+P:	James Courtier-Dutton
+M:	James@superbug.demon.co.uk
 L:	emu10k1-devel@lists.sourceforge.net
 W:	http://sourceforge.net/projects/emu10k1/
 S:	Maintained
@@ -827,10 +836,8 @@
 S:	Maintained
 
 FIRMWARE LOADER (request_firmware)
-P:	Manuel Estrada Sainz
-M:	ranty@debian.org
 L:	linux-kernel@vger.kernel.org
-S:	Maintained
+S:	Orphan
 
 FPU EMULATOR
 P:	Bill Metzenthen
@@ -952,6 +959,12 @@
 W:	http://www.lm-sensors.nu/
 S:	Maintained
 
+I2O
+P:	Markus Lidel
+M:	markus.lidel@shadowconnect.com
+W:	http://i2o.shadowconnect.com/
+S:	Maintained
+
 i386 BOOT CODE
 P:	Riley H. Williams
 M:	Riley@Williams.Name
@@ -1329,6 +1342,18 @@
 W:	http://lsm.immunix.org
 S:	Supported
 
+LM83 HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
+S:	Maintained
+
+LM90 HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
+S:	Maintained
+
 LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks)
 P:	Richard Russon (FlatCap)
 M:	ldm@flatcap.org
@@ -1506,7 +1531,7 @@
 
 NETWORKING [IPv4/IPv6]
 P:	David S. Miller
-M:	davem@redhat.com
+M:	davem@davemloft.net
 P:	Alexey Kuznetsov
 M:	kuznet@ms2.inr.ac.ru
 P:	Pekka Savola (ipv6)
@@ -1908,6 +1933,12 @@
 W:	http://www.winischhofer.net/linuxsisvga.shtml
 S:	Maintained	
 
+SMSC47M1 HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
+S:	Odd Fixes
+
 SMB FILESYSTEM
 P:	Urban Widmark
 M:	urban@teststation.com
@@ -1958,7 +1989,7 @@
 
 UltraSPARC (sparc64):
 P:	David S. Miller
-M:	davem@redhat.com
+M:	davem@davemloft.net
 P:	Eddie C. Dost
 M:	ecd@skynet.be
 P:	Jakub Jelinek
@@ -2411,6 +2442,12 @@
 M:	johnpol@2ka.mipt.ru
 L:	sensors@stimpy.netroedge.com
 S:	Maintained
+
+W83L785TS HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
+S:	Odd Fixes
 
 WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
 P:	Nenad Corbic
diff -Nru a/Makefile b/Makefile
--- a/Makefile	2004-08-23 23:59:52 -07:00
+++ b/Makefile	2004-08-29 04:33:39 -07:00
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 9
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc1-bk5
 NAME=Zonked Quokka
 
 # *DOCUMENTATION*
@@ -279,8 +279,8 @@
 
 # cc-version
 # Usage gcc-ver := $(call cc-version $(CC))
-cc-version = $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
-              $(if $(1), $(1), $(CC))
+cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
+              $(if $(1), $(1), $(CC)))
 
 
 # Look for make include files relative to root of kernel src
diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
--- a/arch/alpha/kernel/irq.c	2004-07-13 05:38:32 -07:00
+++ b/arch/alpha/kernel/irq.c	2004-08-26 23:30:30 -07:00
@@ -288,31 +288,6 @@
 	return full_count;
 }
 
-static int
-prof_cpu_mask_read_proc(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int
-prof_cpu_mask_write_proc(struct file *file, const char __user *buffer,
-			 unsigned long count, void *data)
-{
-	unsigned long full_count = count, err;
-	cpumask_t new_value, *mask = (cpumask_t *)data;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
 #endif /* CONFIG_SMP */
 
 #define MAX_NAMELEN 10
@@ -350,8 +325,6 @@
 #endif
 }
 
-unsigned long prof_cpu_mask = ~0UL;
-
 void
 init_irq_proc (void)
 {
@@ -365,12 +338,7 @@
 
 #ifdef CONFIG_SMP 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 #endif
 
 	/*
diff -Nru a/arch/alpha/kernel/irq_impl.h b/arch/alpha/kernel/irq_impl.h
--- a/arch/alpha/kernel/irq_impl.h	2002-10-31 14:39:26 -08:00
+++ b/arch/alpha/kernel/irq_impl.h	2004-08-26 23:30:31 -07:00
@@ -40,32 +40,3 @@
 extern void init_i8259a_irqs(void);
 
 extern void handle_irq(int irq, struct pt_regs * regs);
-
-extern unsigned long prof_cpu_mask;
-
-static inline void
-alpha_do_profile(unsigned long pc)
-{
-	extern char _stext;
-
-	if (!prof_buffer)
-		return;
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	pc -= (unsigned long) &_stext;
-	pc >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds PC values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (pc > prof_len - 1)
-		pc = prof_len - 1;
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
--- a/arch/alpha/kernel/process.c	2004-07-15 10:56:07 -07:00
+++ b/arch/alpha/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -246,8 +246,7 @@
 	if (!usp)
 		usp = rdusp();
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
-		       parent_tid, child_tid);
+	return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
 }
 
 int
diff -Nru a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
--- a/arch/alpha/kernel/signal.c	2004-07-15 10:56:07 -07:00
+++ b/arch/alpha/kernel/signal.c	2004-08-25 10:13:42 -07:00
@@ -469,9 +469,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void
@@ -533,9 +531,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 
@@ -608,21 +604,20 @@
 	siginfo_t info;
 	int signr;
 	unsigned long single_stepping = ptrace_cancel_bpt(current);
+	struct k_sigaction ka;
 
 	if (!oldset)
 		oldset = &current->blocked;
 
 	/* This lets the debugger run, ... */
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	/* ... so re-check the single stepping. */
 	single_stepping |= ptrace_cancel_bpt(current);
 
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		struct k_sigaction *ka = &current->sighand->action[signr-1];
-
-		if (r0) syscall_restart(r0, r19, regs, ka);
-		handle_signal(signr, ka, &info, oldset, regs, sw);
+		if (r0) syscall_restart(r0, r19, regs, &ka);
+		handle_signal(signr, &ka, &info, oldset, regs, sw);
 		if (single_stepping) 
 			ptrace_set_bpt(current); /* re-set bpt */
 		return 1;
diff -Nru a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
--- a/arch/alpha/kernel/smp.c	2004-07-13 05:39:39 -07:00
+++ b/arch/alpha/kernel/smp.c	2004-08-26 23:30:31 -07:00
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <linux/irq.h>
 #include <linux/cache.h>
+#include <linux/profile.h>
 
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
@@ -411,15 +412,6 @@
 	return 0;
 }
 
-static struct task_struct * __init
-fork_by_hand(void)
-{
-	/* Don't care about the contents of regs since we'll never
-	   reschedule the forked task. */
-	struct pt_regs regs;
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 /*
  * Bring one cpu online.
  */
@@ -435,15 +427,10 @@
 	   the other task-y sort of data structures set up like we
 	   wish.  We can't use kernel_thread since we must avoid
 	   rescheduling the child.  */
-	idle = fork_by_hand();
+	idle = fork_idle(cpuid);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpuid);
 
-	wake_up_forked_process(idle);
-
-	init_idle(idle, cpuid);
-	unhash_process(idle);
-
 	DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
 	      cpuid, idle->state, idle->flags));
 
@@ -613,8 +600,7 @@
 	struct cpuinfo_alpha *data = &cpu_data[cpu];
 
 	/* Record kernel PC.  */
-	if (!user)
-		alpha_do_profile(regs->pc);
+	profile_tick(CPU_PROFILING, regs);
 
 	if (!--data->prof_counter) {
 		/* We need to make like a normal interrupt -- otherwise
diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
--- a/arch/alpha/kernel/time.c	2004-06-29 07:44:50 -07:00
+++ b/arch/alpha/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -41,6 +41,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/bcd.h>
+#include <linux/profile.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -118,8 +119,7 @@
 
 #ifndef CONFIG_SMP
 	/* Not SMP, do kernel PC profiling here.  */
-	if (!user_mode(regs))
-		alpha_do_profile(regs->pc);
+	profile_tick(CPU_PROFILING, regs);
 #endif
 
 	write_seqlock(&xtime_lock);
@@ -366,7 +366,7 @@
 		BCD_TO_BIN(year);
 	}
 
-	/* PC-like is standard; used for year < 20 || year >= 70 */
+	/* PC-like is standard; used for year >= 70 */
 	epoch = 1900;
 	if (year < 20)
 		epoch = 2000;
diff -Nru a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
--- a/arch/alpha/kernel/vmlinux.lds.S	2004-04-12 10:53:59 -07:00
+++ b/arch/alpha/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -46,11 +46,6 @@
   __setup_end = .;
 
   . = ALIGN(8);
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
-
-  . = ALIGN(8);
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
--- a/arch/alpha/mm/numa.c	2004-06-24 01:55:57 -07:00
+++ b/arch/alpha/mm/numa.c	2004-08-24 02:08:33 -07:00
@@ -313,7 +313,7 @@
 			zones_size[ZONE_DMA] = dma_local_pfn;
 			zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
 		}
-		free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn, NULL);
+		free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL);
 	}
 
 	/* Initialize the kernel's ZERO_PGE. */
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig	2004-08-23 15:41:21 -07:00
+++ b/arch/arm/Kconfig	2004-08-27 13:05:05 -07:00
@@ -402,7 +402,7 @@
 
 config FPE_NWFPE_XP
 	bool "Support extended precision"
-	depends on FPE_NWFPE
+	depends on FPE_NWFPE && !CPU_BIG_ENDIAN
 	help
 	  Say Y to include 80-bit support in the kernel floating-point
 	  emulator.  Otherwise, only 32 and 64-bit support is compiled in.
@@ -428,6 +428,7 @@
 
 config VFP
 	bool "VFP-format floating point maths"
+	depends on CPU_V6 || CPU_ARM926T
 	help
 	  Say Y to include VFP support code in the kernel. This is needed
 	  if your hardware includes a VFP unit.
diff -Nru a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
--- a/arch/arm/boot/compressed/Makefile	2004-08-09 10:19:57 -07:00
+++ b/arch/arm/boot/compressed/Makefile	2004-08-27 13:05:05 -07:00
@@ -8,11 +8,13 @@
 OBJS	= misc.o
 FONTC	= drivers/video/console/font_acorn_8x8.c
 
+FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o)
+
 #
 # Architecture dependencies
 #
 ifeq ($(CONFIG_ARCH_ACORN),y)
-OBJS		+= ll_char_wr.o font.o
+OBJS		+= ll_char_wr.o $(FONT)
 endif
 
 ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -66,7 +68,7 @@
 
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-targets       := vmlinux vmlinux.lds piggy.gz piggy.o font.o \
+targets       := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \
 		 head.o misc.o $(OBJS)
 EXTRA_CFLAGS  := -fpic
 EXTRA_AFLAGS  :=
@@ -98,8 +100,7 @@
 
 $(obj)/piggy.o:  $(obj)/piggy.gz FORCE
 
-CFLAGS_font.o := -Dstatic=
-$(obj)/font.o: $(FONTC)
+CFLAGS_font_acorn_8x8.o := -Dstatic=
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
 	@sed "$(SEDFLAGS)" < $< > $@
diff -Nru a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
--- a/arch/arm/common/dmabounce.c	2004-06-17 16:11:01 -07:00
+++ b/arch/arm/common/dmabounce.c	2004-08-25 12:10:44 -07:00
@@ -121,9 +121,9 @@
 	DO_STATS ( device_info->total_allocs++ );
 
 	buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
-	if (buf == 0) {
+	if (buf == NULL) {
 		dev_warn(dev, "%s: kmalloc failed\n", __func__);
-		return 0;
+		return NULL;
 	}
 
 	if (size <= device_info->small_buffer_size) {
@@ -137,16 +137,16 @@
 
 		DO_STATS ( device_info->lbp_allocs++ );
 	} else {
-		pool = 0;
+		pool = NULL;
 		safe = dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC);
 	}
 
-	if (safe == 0) {
+	if (safe == NULL) {
 		dev_warn(device_info->dev,
 			"%s: could not alloc dma memory (size=%d)\n",
 		       __func__, size);
 		kfree(buf);
-		return 0;
+		return NULL;
 	}
 
 #ifdef STATS
@@ -216,27 +216,33 @@
 map_single(struct device *dev, void *ptr, size_t size,
 		enum dma_data_direction dir)
 {
-	dma_addr_t dma_addr;
 	struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+	dma_addr_t dma_addr;
+	int needs_bounce = 0;
 
 	if (device_info)
 		DO_STATS ( device_info->map_op_count++ );
 
+	dma_addr = virt_to_dma(dev, ptr);
+
 	if (dev->dma_mask) {
+		unsigned long mask = *dev->dma_mask;
 		unsigned long limit;
 
-		limit = (*dev->dma_mask + 1) & ~(*dev->dma_mask);
-		if (limit && (size > limit)) {
-			dev_err(dev, "DMA mapping too big "
-				"(requested %#x mask %#Lx)\n",
-				size, *dev->dma_mask);
+		limit = (mask + 1) & ~mask;
+		if (limit && size > limit) {
+			dev_err(dev, "DMA mapping too big (requested %#x "
+				"mask %#Lx)\n", size, *dev->dma_mask);
 			return ~0;
 		}
-	}
 
-	dma_addr = virt_to_dma(dev, ptr);
+		/*
+		 * Figure out if we need to bounce from the DMA mask.
+		 */
+		needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
+	}
 
-	if (device_info && dma_needs_bounce(dev, dma_addr, size)) {
+	if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
 		struct safe_buffer *buf;
 
 		buf = alloc_safe_buffer(device_info, ptr, size, dir);
diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
--- a/arch/arm/common/sa1111.c	2004-07-06 02:42:22 -07:00
+++ b/arch/arm/common/sa1111.c	2004-08-25 06:27:11 -07:00
@@ -761,9 +761,6 @@
  */
 int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
 {
-	unsigned int physaddr = SA1111_DMA_ADDR((unsigned int)addr);
-	u32 dma_mask = *dev->dma_mask;
-
 	/*
 	 * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
 	 * User's Guide" mentions that jumpers R51 and R52 control the
@@ -771,14 +768,8 @@
 	 * SDRAM bank 1 on Neponset). The default configuration selects
 	 * Assabet, so any address in bank 1 is necessarily invalid.
 	 */
-	if ((machine_is_assabet() || machine_is_pfs168()) &&
-		(addr >= 0xc8000000 || (addr + size) >= 0xc8000000))
-	  	return 1;
-
-	/*
-	 * Check to see if either the start or end are illegal.
-	 */
-	return ((addr & ~dma_mask)) || ((addr + size - 1) & ~dma_mask);
+	return ((machine_is_assabet() || machine_is_pfs168()) &&
+		(addr >= 0xc8000000 || (addr + size) >= 0xc8000000));
 }
 
 struct sa1111_save_data {
diff -Nru a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
--- a/arch/arm/kernel/armksyms.c	2004-05-16 06:10:42 -07:00
+++ b/arch/arm/kernel/armksyms.c	2004-08-25 18:47:39 -07:00
@@ -105,6 +105,7 @@
 EXPORT_SYMBOL_NOVERS(memmove);
 EXPORT_SYMBOL_NOVERS(memcmp);
 EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL_NOVERS(memchr);
 EXPORT_SYMBOL_NOVERS(__memzero);
 
 	/* user mem (segment) */
diff -Nru a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
--- a/arch/arm/kernel/signal.c	2004-06-18 10:58:27 -07:00
+++ b/arch/arm/kernel/signal.c	2004-08-26 14:32:42 -07:00
@@ -573,12 +573,12 @@
  * OK, we're invoking a handler
  */	
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset,
 	      struct pt_regs * regs, int syscall)
 {
 	struct thread_info *thread = current_thread_info();
 	struct task_struct *tsk = current;
-	struct k_sigaction *ka = &tsk->sighand->action[sig-1];
 	int usig = sig;
 	int ret;
 
@@ -633,15 +633,10 @@
 		spin_unlock_irq(&tsk->sighand->siglock);
 	}
 
-	if (ret == 0) {
-		if (ka->sa.sa_flags & SA_ONESHOT)
-			ka->sa.sa_handler = SIG_DFL;
+	if (ret == 0)
 		return;
-	}
 
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, tsk);
+	force_sigsegv(sig, tsk);
 }
 
 /*
@@ -655,6 +650,7 @@
  */
 static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 {
+	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
@@ -675,9 +671,9 @@
 	if (current->ptrace & PT_SINGLESTEP)
 		ptrace_cancel_bpt(current);
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
-		handle_signal(signr, &info, oldset, regs, syscall);
+		handle_signal(signr, &ka, &info, oldset, regs, syscall);
 		if (current->ptrace & PT_SINGLESTEP)
 			ptrace_set_bpt(current);
 		return 1;
diff -Nru a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
--- a/arch/arm/kernel/sys_arm.c	2004-07-30 08:28:47 -07:00
+++ b/arch/arm/kernel/sys_arm.c	2004-08-25 12:10:44 -07:00
@@ -217,11 +217,8 @@
 				return ret;
 			return put_user(raddr, (ulong __user *)third);
 		}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				return -EINVAL;
-			return do_shmat(first, (char __user *) ptr,
-					second, (ulong __user *) third);
+		case 1: /* Of course, we don't support iBCS2! */
+			return -EINVAL;
 		}
 	case SHMDT: 
 		return sys_shmdt ((char __user *)ptr);
@@ -257,7 +254,7 @@
 	if (!newsp)
 		newsp = regs->ARM_sp;
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+	return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 }
 
 asmlinkage int sys_vfork(struct pt_regs *regs)
diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c	2004-06-17 14:21:25 -07:00
+++ b/arch/arm/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -79,31 +79,6 @@
 	return (unsigned long long)jiffies * (1000000000 / HZ);
 }
 
-/*
- * Handle kernel profile stuff...
- */
-static inline void do_profile(struct pt_regs *regs)
-{
-
-	profile_hook(regs);
-
-	if (!user_mode(regs) &&
-	    prof_buffer &&
-	    current->pid) {
-		unsigned long pc = instruction_pointer(regs);
-		extern int _stext;
-
-		pc -= (unsigned long)&_stext;
-
-		pc >>= prof_shift;
-
-		if (pc >= prof_len)
-			pc = prof_len - 1;
-
-		prof_buffer[pc] += 1;
-	}
-}
-
 static unsigned long next_rtc_update;
 
 /*
@@ -317,7 +292,7 @@
 
 void timer_tick(struct pt_regs *regs)
 {
-	do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 	do_leds();
 	do_set_rtc();
 	do_timer(regs);
diff -Nru a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
--- a/arch/arm/kernel/vmlinux.lds.S	2004-04-12 10:53:59 -07:00
+++ b/arch/arm/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -38,9 +38,6 @@
 		__early_begin = .;
 			*(__early_param)
 		__early_end = .;
-		__start___param = .;
-			*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 			*(.initcall1.init)
 			*(.initcall2.init)
diff -Nru a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
--- a/arch/arm/mach-s3c2410/clock.c	2004-08-08 13:31:03 -07:00
+++ b/arch/arm/mach-s3c2410/clock.c	2004-08-20 16:32:37 -07:00
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/gpio.c
+/* linux/arch/arm/mach-s3c2410/clock.c
  *
  * Copyright (c) 2004 Simtec Electronics
  * Ben Dooks <ben@simtec.co.uk>
@@ -99,7 +99,9 @@
 
 int clk_enable(struct clk *clk)
 {
-	s3c2410_clk_enable(clk->ctrlbit, 1);
+	if (clk->ctrlbit != 0)
+		s3c2410_clk_enable(clk->ctrlbit, 1);
+
 	return 0;
 }
 
@@ -240,6 +242,10 @@
 	{ .name    = "spi",
 	  .parent  = &clk_p,
 	  .ctrlbit = S3C2410_CLKCON_SPI
+	},
+	{ .name    = "watchdog",
+	  .parent  = &clk_p,
+	  .ctrlbit = 0
 	}
 };
 
@@ -284,10 +290,10 @@
 		printk(KERN_ERR "failed to register cpu fclk\n");
 
 	if (s3c2410_register_clock(&clk_h) < 0)
-		printk(KERN_ERR "failed to register cpu fclk\n");
+		printk(KERN_ERR "failed to register cpu hclk\n");
 
 	if (s3c2410_register_clock(&clk_p) < 0)
-		printk(KERN_ERR "failed to register cpu fclk\n");
+		printk(KERN_ERR "failed to register cpu pclk\n");
 
 	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
 		ret = s3c2410_register_clock(clkp);
diff -Nru a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
--- a/arch/arm/mach-s3c2410/devs.c	2004-08-18 10:44:07 -07:00
+++ b/arch/arm/mach-s3c2410/devs.c	2004-08-21 02:13:16 -07:00
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     21-Aug-2004 BJD  Added IRQ_TICK to RTC resources
  *     18-Aug-2004 BJD  Created initial version
 */
 
@@ -229,8 +230,12 @@
 		.start = IRQ_RTC,
 		.end   = IRQ_RTC,
 		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = IRQ_TICK,
+		.end   = IRQ_TICK,
+		.flags = IORESOURCE_IRQ
 	}
-
 };
 
 struct platform_device s3c_device_rtc = {
diff -Nru a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
--- a/arch/arm/mach-s3c2410/mach-bast.c	2004-06-15 17:42:35 -07:00
+++ b/arch/arm/mach-s3c2410/mach-bast.c	2004-08-20 18:45:25 -07:00
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/mach-bast.c
  *
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003,2004 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * http://www.simtec.co.uk/products/EB2410ITX/
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     20-Aug-2004 BJD  Added s3c2410_board struct
+ *     18-Aug-2004 BJD  Added platform devices from default set
  *     16-May-2003 BJD  Created initial version
  *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
  *     05-Sep-2003 BJD  Moved to v2.6 kernel
@@ -23,6 +25,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/device.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -39,6 +42,7 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
 
 /* macros for virtual address mods for the io space entries */
 #define VA_C5(item) ((item) + BAST_VAM_CS5)
@@ -154,6 +158,7 @@
 	[1] = {
 		.hwport	     = 1,
 		.flags	     = 0,
+
 		.clock	     = &bast_serial_clock,
 		.ucon	     = UCON,
 		.ulcon	     = ULCON,
@@ -170,19 +175,30 @@
 	}
 };
 
+static struct platform_device *bast_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c2410_board bast_board __initdata = {
+	.devices       = bast_devices,
+	.devices_count = ARRAY_SIZE(bast_devices)
+};
 
 void __init bast_map_io(void)
 {
 	s3c2410_map_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
 	s3c2410_uartcfgs = bast_uartcfgs;
+
+	s3c2410_set_board(&bast_board);
 }
 
 void __init bast_init_irq(void)
 {
-	//llprintk("bast_init_irq:\n");
-
 	s3c2410_init_irq();
-
 }
 
 void __init bast_init_time(void)
diff -Nru a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
--- a/arch/arm/mach-s3c2410/mach-h1940.c	2004-07-18 23:10:55 -07:00
+++ b/arch/arm/mach-s3c2410/mach-h1940.c	2004-08-20 18:46:58 -07:00
@@ -1,6 +1,6 @@
-/* linux/arch/arm/mach-s3c2410/mach-ipaq.c
+/* linux/arch/arm/mach-s3c2410/mach-h1940.c
  *
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003,2004 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * http://www.handhelds.org/projects/h1940.html
@@ -16,6 +16,7 @@
  *     06-Jan-2003 BJD  Updates for <arch/map.h>
  *     18-Jan-2003 BJD  Added serial port configuration
  *     17-Feb-2003 BJD  Copied to mach-ipaq.c
+ *     21-Aug-2004 BJD  Added struct s3c2410_board
 */
 
 #include <linux/kernel.h>
@@ -39,6 +40,7 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
 
 static struct map_desc ipaq_iodesc[] __initdata = {
 	/* nothing here yet */
@@ -77,10 +79,27 @@
 };
 
 
+
+
+static struct platform_device *h1940_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c2410_board h1940_board __initdata = {
+	.devices       = h1940_devices,
+	.devices_count = ARRAY_SIZE(h1940_devices)
+};
+
 void __init ipaq_map_io(void)
 {
 	s3c2410_map_io(ipaq_iodesc, ARRAY_SIZE(ipaq_iodesc));
 	s3c2410_uartcfgs = ipaq_uartcfgs;
+
+	s3c2410_set_board(&h1940_board);
 }
 
 void __init ipaq_init_irq(void)
diff -Nru a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c	2004-08-06 03:07:53 -07:00
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c	2004-08-20 18:47:20 -07:00
@@ -47,7 +47,7 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
-
+#include "devs.h"
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
@@ -87,11 +87,25 @@
 	}
 };
 
+static struct platform_device *smdk2410_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c2410_board smdk2410_board __initdata = {
+	.devices       = smdk2410_devices,
+	.devices_count = ARRAY_SIZE(smdk2410_devices)
+};
 
 void __init smdk2410_map_io(void)
 {
 	s3c2410_map_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
 	s3c2410_uartcfgs = smdk2410_uartcfgs;
+
+	s3c2410_set_board(&smdk2410_board);
 }
 
 void __init smdk2410_init_irq(void)
diff -Nru a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
--- a/arch/arm/mach-s3c2410/mach-vr1000.c	2004-08-06 03:09:08 -07:00
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c	2004-08-20 18:47:09 -07:00
@@ -11,13 +11,8 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     21-Aug-2004 BJD  Added struct s3c2410_board
  *     06-Aug-2004 BJD  Fixed call to time initialisation
- *     12-Jul-2004 BJD  Renamed machine
- *     16-May-2003 BJD  Created initial version
- *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
- *     05-Sep-2003 BJD  Moved to v2.6 kernel
- *     06-Jan-2003 BJD  Updates for <arch/map.h>
- *     18-Jan-2003 BJD  Added serial port configuration
  *     05-Apr-2004 BJD  Copied to make mach-vr1000.c
 */
 
@@ -44,6 +39,7 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
 
 /* macros for virtual address mods for the io space entries */
 #define VA_C5(item) ((item) + BAST_VAM_CS5)
@@ -143,11 +139,26 @@
 	}
 };
 
+static struct platform_device *vr1000_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c2410_board vr1000_board __initdata = {
+	.devices       = vr1000_devices,
+	.devices_count = ARRAY_SIZE(vr1000_devices)
+};
+
 
 void __init vr1000_map_io(void)
 {
 	s3c2410_map_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
 	s3c2410_uartcfgs = vr1000_uartcfgs;
+
+	s3c2410_set_board(&vr1000_board);
 }
 
 void __init vr1000_init_irq(void)
diff -Nru a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
--- a/arch/arm/mach-s3c2410/s3c2410.c	2004-05-24 09:11:50 -07:00
+++ b/arch/arm/mach-s3c2410/s3c2410.c	2004-08-20 18:40:26 -07:00
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/s3c2410.c
  *
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003,2004 Simtec Electronics
  * Ben Dooks <ben@simtec.co.uk>
  *
  * http://www.simtec.co.uk/products/EB2410ITX/
@@ -13,7 +13,8 @@
  *     16-May-2003 BJD  Created initial version
  *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
  *     05-Sep-2003 BJD  Moved to kernel v2.6
- *     18-Jan-2003 BJD  Added serial port configuration
+ *     18-Jan-2004 BJD  Added serial port configuration
+ *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
 */
 
 #include <linux/kernel.h>
@@ -35,6 +36,8 @@
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-serial.h>
 
+#include "s3c2410.h"
+
 int s3c2410_clock_tick_rate = 12*1000*1000;  /* current timers at 12MHz */
 
 /* serial port setup */
@@ -56,24 +59,15 @@
 #define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
 
 static struct map_desc s3c2410_iodesc[] __initdata = {
-  IODESC_ENT(IRQ),
-  IODESC_ENT(MEMCTRL),
-  IODESC_ENT(USBHOST),
-  IODESC_ENT(DMA),
-  IODESC_ENT(CLKPWR),
-  IODESC_ENT(LCD),
-  IODESC_ENT(NAND),
-  IODESC_ENT(UART),
-  IODESC_ENT(TIMER),
-  IODESC_ENT(USBDEV),
-  IODESC_ENT(WATCHDOG),
-  IODESC_ENT(IIC),
-  IODESC_ENT(IIS),
-  IODESC_ENT(GPIO),
-  IODESC_ENT(RTC),
-  IODESC_ENT(ADC),
-  IODESC_ENT(SPI),
-  IODESC_ENT(SDI)
+	IODESC_ENT(IRQ),
+	IODESC_ENT(MEMCTRL),
+	IODESC_ENT(USBHOST),
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(LCD),
+	IODESC_ENT(UART),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(GPIO),
+	IODESC_ENT(ADC),
 };
 
 static struct resource s3c_uart0_resource[] = {
@@ -175,6 +169,12 @@
 	       print_mhz(s3c2410_pclk));
 }
 
+static struct s3c2410_board *board;
+
+void s3c2410_set_board(struct s3c2410_board *b)
+{
+	board = b;
+}
 
 static int __init s3c2410_init(void)
 {
@@ -183,6 +183,22 @@
 	printk("S3C2410: Initialising architecture\n");
 
 	ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
+	if (ret)
+		return ret;
+
+	if (board != NULL) {
+		if (board->devices != NULL) {
+			ret = platform_add_devices(board->devices,
+						   board->devices_count);
+
+			if (ret) {
+				printk(KERN_ERR "s3c2410: failed to add board devices (%d)\n", ret);
+			}
+		}
+
+		/* not adding board devices may not be fatal */
+		ret = 0;
+	}
 
 	return ret;
 }
diff -Nru a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
--- a/arch/arm/mach-s3c2410/s3c2410.h	2004-08-18 10:21:12 -07:00
+++ b/arch/arm/mach-s3c2410/s3c2410.h	2004-08-20 17:12:12 -07:00
@@ -11,7 +11,7 @@
  *
  * Modifications:
  *     18-Aug-2004 BJD  Created initial version
- *
+ *     20-Aug-2004 BJD  Added s3c2410_board struct
 */
 
 extern void s3c2410_map_io(struct map_desc *, int count);
@@ -20,3 +20,16 @@
 
 extern void s3c2410_init_time(void);
 
+/* the board structure is used at first initialsation time
+ * to get info such as the devices to register for this
+ * board. This is done because platfrom_add_devices() cannot
+ * be called from the map_io entry.
+ *
+*/
+
+struct s3c2410_board {
+	struct platform_device  **devices;
+	unsigned int              devices_count;
+};
+
+extern void s3c2410_set_board(struct s3c2410_board *board);
diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c
--- a/arch/arm/mm/init.c	2004-08-15 05:36:41 -07:00
+++ b/arch/arm/mm/init.c	2004-08-24 02:08:33 -07:00
@@ -495,7 +495,7 @@
 		 */
 		arch_adjust_zones(node, zone_size, zhole_size);
 
-		free_area_init_node(node, pgdat, NULL, zone_size,
+		free_area_init_node(node, pgdat, zone_size,
 				bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
 	}
 
diff -Nru a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
--- a/arch/arm/nwfpe/fpa11_cpdt.c	2004-08-08 08:02:27 -07:00
+++ b/arch/arm/nwfpe/fpa11_cpdt.c	2004-08-18 15:52:12 -07:00
@@ -42,8 +42,13 @@
 	unsigned int *p;
 	p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
 	fpa11->fType[Fn] = typeDouble;
+#ifdef __ARMEB__
+	get_user(p[0], &pMem[0]);	/* sign & exponent */
+	get_user(p[1], &pMem[1]);
+#else
 	get_user(p[0], &pMem[1]);
 	get_user(p[1], &pMem[0]);	/* sign & exponent */
+#endif
 }
 
 #ifdef CONFIG_FPE_NWFPE_XP
@@ -140,8 +145,13 @@
 		val.f = fpa11->fpreg[Fn].fDouble;
 	}
 
+#ifdef __ARMEB__
+	put_user(val.i[0], &pMem[0]);	/* msw */
+	put_user(val.i[1], &pMem[1]);	/* lsw */
+#else
 	put_user(val.i[1], &pMem[0]);	/* msw */
 	put_user(val.i[0], &pMem[1]);	/* lsw */
+#endif
 }
 
 #ifdef CONFIG_FPE_NWFPE_XP
diff -Nru a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c
--- a/arch/arm/oprofile/op_model_xscale.c	2004-08-21 13:28:53 -07:00
+++ b/arch/arm/oprofile/op_model_xscale.c	2004-08-24 02:08:43 -07:00
@@ -30,6 +30,7 @@
 #define PMN_RESET	0x002	/* Reset event counters */
 #define	CCNT_RESET	0x004	/* Reset clock counter */
 #define	PMU_RESET	(CCNT_RESET | PMN_RESET)
+#define PMU_CNT64	0x008	/* Make CCNT count every 64th cycle */
 
 /* TODO do runtime detection */
 #ifdef CONFIG_ARCH_IOP310
@@ -125,12 +126,15 @@
 
 static void write_pmnc(u32 val)
 {
-	/* upper 4bits and 7, 11 are write-as-0 */
-	val &= 0xffff77f;
-	if (pmu->id == PMU_XSC1)
+	if (pmu->id == PMU_XSC1) {
+		/* upper 4bits and 7, 11 are write-as-0 */
+		val &= 0xffff77f;
 		__asm__ __volatile__ ("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
-	else
+	} else {
+		/* bits 4-23 are write-as-0, 24-31 are write ignored */
+		val &= 0xf;
 		__asm__ __volatile__ ("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
+	}
 }
 
 static u32 read_pmnc(void)
@@ -139,8 +143,11 @@
 
 	if (pmu->id == PMU_XSC1)
 		__asm__ __volatile__ ("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
-	else
+	else {
 		__asm__ __volatile__ ("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
+		/* bits 1-2 and 4-23 are read-unpredictable */
+		val &= 0xff000009;
+	}
 
 	return val;
 }
@@ -386,8 +393,10 @@
 
 	if (pmu->id == PMU_XSC1)
 		pmnc |= pmu->int_enable;
-	else
+	else {
 		__asm__ __volatile__ ("mcr p14, 0, %0, c4, c1, 0" : : "r" (pmu->int_enable));
+		pmnc &= ~PMU_CNT64;
+	}
 
 	pmnc |= PMU_ENABLE;
 	write_pmnc(pmnc);
diff -Nru a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c
--- a/arch/arm26/kernel/signal.c	2003-06-04 04:15:45 -07:00
+++ b/arch/arm26/kernel/signal.c	2004-08-25 17:37:25 -07:00
@@ -465,9 +465,7 @@
 		return;
 	}
 
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, tsk);
+	force_sigsegv(sig, tsk);
 }
 
 /*
diff -Nru a/arch/arm26/kernel/sys_arm.c b/arch/arm26/kernel/sys_arm.c
--- a/arch/arm26/kernel/sys_arm.c	2004-03-31 05:28:58 -08:00
+++ b/arch/arm26/kernel/sys_arm.c	2004-08-24 02:08:42 -07:00
@@ -256,7 +256,7 @@
 	if (!newsp)
 		newsp = regs->ARM_sp;
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+	return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 }
 
 asmlinkage int sys_vfork(struct pt_regs *regs)
diff -Nru a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c
--- a/arch/arm26/kernel/time.c	2004-02-18 19:43:10 -08:00
+++ b/arch/arm26/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -67,28 +67,6 @@
  */
 unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset;
 
-/*
- * Handle kernel profile stuff...
- */
-static inline void do_profile(struct pt_regs *regs)
-{
-	if (!user_mode(regs) &&
-	    prof_buffer &&
-	    current->pid) {
-		unsigned long pc = instruction_pointer(regs);
-		extern int _stext;
-
-		pc -= (unsigned long)&_stext;
-
-		pc >>= prof_shift;
-
-		if (pc >= prof_len)
-			pc = prof_len - 1;
-
-		prof_buffer[pc] += 1;
-	}
-}
-
 static unsigned long next_rtc_update;
 
 /*
@@ -189,7 +167,7 @@
 {
         do_timer(regs);
         do_set_rtc(); //FIME - EVERY timer IRQ?
-        do_profile(regs);
+        profile_tick(CPU_PROFILING, regs);
 	return IRQ_HANDLED; //FIXME - is this right?
 }
 
diff -Nru a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
--- a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2004-04-12 10:53:59 -07:00
+++ b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2004-08-24 02:08:55 -07:00
@@ -34,9 +34,6 @@
 		__early_begin = .;
 			*(__early_param)
 		__early_end = .;
-		__start___param = .;
-			*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 			*(.initcall1.init)
 			*(.initcall2.init)
diff -Nru a/arch/arm26/kernel/vmlinux-arm26.lds.in b/arch/arm26/kernel/vmlinux-arm26.lds.in
--- a/arch/arm26/kernel/vmlinux-arm26.lds.in	2004-04-12 10:53:59 -07:00
+++ b/arch/arm26/kernel/vmlinux-arm26.lds.in	2004-08-24 02:08:55 -07:00
@@ -35,9 +35,6 @@
 		__early_begin = .;
 			*(__early_param)
 		__early_end = .;
-		__start___param = .;
-			*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 			*(.initcall1.init)
 			*(.initcall2.init)
diff -Nru a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
--- a/arch/arm26/mm/init.c	2004-06-24 01:55:57 -07:00
+++ b/arch/arm26/mm/init.c	2004-08-24 11:05:57 -07:00
@@ -305,8 +305,8 @@
 			(bdata->node_boot_start >> PAGE_SHIFT);
 	if (!zone_size[0])
 		BUG();
-
-	free_area_init_node(0, pgdat, 0, zone_size,
+	pgdat->node_mem_map = NULL;
+	free_area_init_node(0, pgdat, zone_size,
 			bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
 
 	mem_map = NODE_DATA(0)->node_mem_map;
diff -Nru a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c
--- a/arch/cris/arch-v10/kernel/debugport.c	2004-06-01 02:27:58 -07:00
+++ b/arch/cris/arch-v10/kernel/debugport.c	2004-08-27 00:02:36 -07:00
@@ -259,7 +259,7 @@
 void __init 
 init_etrax_debug(void)
 {
-#if CONFIG_ETRAX_DEBUG_PORT_NULL
+#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL
 	return;
 #endif
 
diff -Nru a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
--- a/arch/cris/arch-v10/kernel/process.c	2004-06-01 02:27:58 -07:00
+++ b/arch/cris/arch-v10/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -180,7 +180,7 @@
 {
 	if (!newusp)
 		newusp = rdusp();
-	return do_fork(flags & ~CLONE_IDLETASK, newusp, regs, 0, parent_tid, child_tid);
+	return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
 }
 
 /* vfork is a system call in i386 because of register-pressure - maybe
diff -Nru a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
--- a/arch/cris/arch-v10/kernel/signal.c	2004-06-01 02:27:58 -07:00
+++ b/arch/cris/arch-v10/kernel/signal.c	2004-08-25 17:37:25 -07:00
@@ -409,9 +409,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -475,9 +473,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
diff -Nru a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c
--- a/arch/cris/arch-v10/mm/init.c	2003-07-10 10:29:07 -07:00
+++ b/arch/cris/arch-v10/mm/init.c	2004-08-24 11:05:57 -07:00
@@ -183,7 +183,7 @@
 	 * mem_map page array.
 	 */
 
-	free_area_init_node(0, &contig_page_data, 0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
+	free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
 	mem_map = contig_page_data.node_mem_map;
 }
 
diff -Nru a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S
--- a/arch/cris/arch-v10/vmlinux.lds.S	2004-04-12 10:53:59 -07:00
+++ b/arch/cris/arch-v10/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -64,9 +64,6 @@
   	__setup_start = .;
   	.init.setup : { *(.init.setup) }
   	__setup_end = .;
-	__start___param = .;
-	__param : { *(__param) }
-	__stop___param = .;
   	.initcall.init : {
 		__initcall_start = .;
 		*(.initcall1.init);
diff -Nru a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
--- a/arch/h8300/kernel/process.c	2004-05-14 19:00:18 -07:00
+++ b/arch/h8300/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -189,7 +189,7 @@
 	newsp = regs->er2;
 	if (!newsp)
 		newsp  = rdusp();
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+	return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 
 }
 
diff -Nru a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
--- a/arch/h8300/kernel/signal.c	2004-05-14 19:00:16 -07:00
+++ b/arch/h8300/kernel/signal.c	2004-08-25 17:37:25 -07:00
@@ -391,9 +391,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -443,9 +441,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static inline void
diff -Nru a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
--- a/arch/h8300/kernel/time.c	2004-02-18 19:43:10 -08:00
+++ b/arch/h8300/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -36,24 +36,6 @@
 
 EXPORT_SYMBOL(jiffies_64);
 
-static inline void do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		if (pc < prof_len)
-			++prof_buffer[pc];
-		else
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			++prof_buffer[prof_len-1];
-	}
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -64,10 +46,7 @@
 	platform_timer_eoi();
 
 	do_timer(regs);
-
-	if (!user_mode(regs))
-		do_profile(regs->pc);
-
+	profile_tick(CPU_PROFILING, regs);
 }
 
 void time_init(void)
diff -Nru a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
--- a/arch/h8300/kernel/vmlinux.lds.S	2004-05-20 10:44:25 -07:00
+++ b/arch/h8300/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -150,9 +150,6 @@
 		*(.init.setup)
 	. = ALIGN(0x4) ;
 	___setup_end = .;
-	___start___param = .;
-		*(__param)
-	___stop___param = .;
 	___initcall_start = .;
 		*(.initcall1.init)
 		*(.initcall2.init)
diff -Nru a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
--- a/arch/i386/Kconfig.debug	2004-08-15 12:45:24 -07:00
+++ b/arch/i386/Kconfig.debug	2004-08-24 02:08:10 -07:00
@@ -45,6 +45,18 @@
 	  on the VM subsystem for higher order allocations. This option
 	  will also use IRQ stacks to compensate for the reduced stackspace.
 
+config SCHEDSTATS
+	bool "Collect scheduler statistics"
+	depends on DEBUG_KERNEL && PROC_FS
+	help
+	  If you say Y here, additional code will be inserted into the
+	  scheduler and related routines to collect statistics about
+	  scheduler behavior and provide them in /proc/schedstat.  These
+	  stats may be useful for both tuning and debugging the scheduler
+	  If you aren't debugging the scheduler or trying to tune a specific
+	  application, you can say N to avoid the very slight overhead
+	  this adds.
+
 config X86_FIND_SMP_CONFIG
 	bool
 	depends on X86_LOCAL_APIC || X86_VOYAGER
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	2004-08-15 03:17:51 -07:00
+++ b/arch/i386/kernel/Makefile	2004-08-26 12:20:27 -07:00
@@ -41,11 +41,14 @@
 # Note: kbuild does not track this dependency due to usage of .incbin
 $(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
 targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
+targets += vsyscall.lds
 
 # The DSO images are built using a special linker script.
 quiet_cmd_syscall = SYSCALL $@
       cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
 		          -Wl,-T,$(filter-out FORCE,$^) -o $@
+
+export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH)
 
 vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
 SYSCFLAGS_vsyscall-sysenter.so	= $(vsyscall-flags)
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
--- a/arch/i386/kernel/apic.c	2004-08-23 01:15:00 -07:00
+++ b/arch/i386/kernel/apic.c	2004-08-26 23:30:31 -07:00
@@ -343,7 +343,7 @@
 
 void __init setup_local_APIC (void)
 {
-	unsigned long value, ver, maxlvt;
+	unsigned long oldvalue, value, ver, maxlvt;
 
 	/* Pound the ESR really hard over the head with a big hammer - mbligh */
 	if (esr_disable) {
@@ -459,9 +459,7 @@
 		maxlvt = get_maxlvt();
 		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
 			apic_write(APIC_ESR, 0);
-		value = apic_read(APIC_ESR);
-		apic_printk(APIC_VERBOSE, "ESR value before enabling vector:"
-				" %08lx\n", value);
+		oldvalue = apic_read(APIC_ESR);
 
 		value = ERROR_APIC_VECTOR;      // enables sending errors
 		apic_write_around(APIC_LVTERR, value);
@@ -471,8 +469,10 @@
 		if (maxlvt > 3)
 			apic_write(APIC_ESR, 0);
 		value = apic_read(APIC_ESR);
-		apic_printk(APIC_VERBOSE, "ESR value after enabling vector:"
-				" %08lx\n", value);
+		if (value != oldvalue)
+			apic_printk(APIC_VERBOSE, "ESR value before enabling "
+				"vector: 0x%08lx  after: 0x%08lx\n",
+				oldvalue, value);
 	} else {
 		if (esr_disable)	
 			/* 
@@ -1071,8 +1071,7 @@
 {
 	int cpu = smp_processor_id();
 
-	x86_do_profile(regs);
-
+	profile_tick(CPU_PROFILING, regs);
 	if (--per_cpu(prof_counter, cpu) <= 0) {
 		/*
 		 * The multiplier may have changed since the last time we got
diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
--- a/arch/i386/kernel/apm.c	2004-08-23 01:14:51 -07:00
+++ b/arch/i386/kernel/apm.c	2004-08-24 02:08:47 -07:00
@@ -2271,10 +2271,12 @@
 	}
 	if ((num_online_cpus() > 1) && !power_off && !smp) {
 		printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+		apm_info.disabled = 1;
 		return -ENODEV;
 	}
 	if (PM_IS_ACTIVE()) {
 		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
+		apm_info.disabled = 1;
 		return -ENODEV;
 	}
 	pm_active = 1;
diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
--- a/arch/i386/kernel/cpu/common.c	2004-08-23 01:14:52 -07:00
+++ b/arch/i386/kernel/cpu/common.c	2004-08-24 02:09:02 -07:00
@@ -559,13 +559,11 @@
 
 	load_esp0(t, thread);
 	set_tss_desc(cpu,t);
-	per_cpu(cpu_gdt_table,cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff;
 	load_TR_desc();
 	load_LDT(&init_mm.context);
 
 	/* Set up doublefault TSS pointer in the GDT */
 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
-	per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_DOUBLEFAULT_TSS].b &= 0xfffffdff;
 
 	/* Clear %fs and %gs. */
 	asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c	2004-08-18 08:46:37 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c	2004-08-24 13:15:16 -07:00
@@ -38,6 +38,17 @@
 
 #define PFX "longhaul: "
 
+#define TYPE_LONGHAUL_V1	1
+#define TYPE_LONGHAUL_V2	2
+#define TYPE_POWERSAVER		3
+
+#define	CPU_SAMUEL	1
+#define	CPU_SAMUEL2	2
+#define	CPU_EZRA	3
+#define	CPU_EZRA_T	4
+#define	CPU_NEHEMIAH	5
+
+static int cpu_model;
 static unsigned int numscales=16, numvscales;
 static unsigned int fsb;
 static int minvid, maxvid;
@@ -73,9 +84,23 @@
 static unsigned int highest_speed, lowest_speed; /* kHz */
 static int longhaul_version;
 static struct cpufreq_frequency_table *longhaul_table;
+static char speedbuffer[8];
+
+static char *print_speed(int speed)
+{
+	if (speed > 1000) {
+		if (speed%1000 == 0)
+			sprintf (speedbuffer, "%dGHz", speed/1000);
+		else
+			sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100);
+	} else
+		sprintf (speedbuffer, "%dMHz", speed);
+
+	return speedbuffer;
+}
 
 
-static unsigned int calc_speed(int mult, int fsb)
+static unsigned int calc_speed(int mult)
 {
 	int khz;
 	khz = (mult/10)*fsb;
@@ -92,7 +117,7 @@
 
 	rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
 	invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22;
-	if (longhaul_version==2 || longhaul_version==3) {
+	if (longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) {
 		if (lo & (1<<27))
 			invalue+=16;
 	}
@@ -101,8 +126,21 @@
 
 
 static void do_powersaver(union msr_longhaul *longhaul,
-			unsigned int clock_ratio_index, int version)
+			unsigned int clock_ratio_index)
 {
+	int version;
+
+	switch (cpu_model) {
+	case CPU_EZRA_T:
+		version = 3;
+		break;
+	case CPU_NEHEMIAH:
+		version = 0xf;
+		break;
+	default:
+		return;
+	}
+
 	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
 	longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
 	longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
@@ -125,7 +163,7 @@
  * longhaul_set_cpu_frequency()
  * @clock_ratio_index : bitpattern of the new multiplier.
  *
- * Sets a new clock ratio, and -if applicable- a new Front Side Bus
+ * Sets a new clock ratio.
  */
 
 static void longhaul_setstate(unsigned int clock_ratio_index)
@@ -134,22 +172,28 @@
 	struct cpufreq_freqs freqs;
 	union msr_longhaul longhaul;
 	union msr_bcr2 bcr2;
+	static unsigned int old_ratio=-1;
+
+	if (old_ratio == clock_ratio_index)
+		return;
+	old_ratio = clock_ratio_index;
 
 	mult = clock_ratio[clock_ratio_index];
 	if (mult == -1)
 		return;
 
-	speed = calc_speed (mult, fsb);
+	speed = calc_speed(mult);
 	if ((speed > highest_speed) || (speed < lowest_speed))
 		return;
 
-	freqs.old = calc_speed (longhaul_get_cpu_mult(), fsb);
+	freqs.old = calc_speed(longhaul_get_cpu_mult());
 	freqs.new = speed;
 	freqs.cpu = 0; /* longhaul.c is UP only driver */
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, mult/10, mult%10);
+	dprintk (KERN_INFO PFX "Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
+			fsb, mult/10, mult%10, print_speed(speed/1000));
 
 	switch (longhaul_version) {
 
@@ -160,7 +204,8 @@
 	 * *NB* Until we get voltage scaling working v1 & v2 are the same code.
 	 * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C]
 	 */
-	case 1:
+	case TYPE_LONGHAUL_V1:
+	case TYPE_LONGHAUL_V2:
 		rdmsrl (MSR_VIA_BCR2, bcr2.val);
 		/* Enable software clock multiplier */
 		bcr2.bits.ESOFTBF = 1;
@@ -180,26 +225,18 @@
 		break;
 
 	/*
-	 * Longhaul v3 (aka Powersaver). (Ezra-T [C5M])
+	 * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
 	 * We can scale voltage with this too, but that's currently
 	 * disabled until we come up with a decent 'match freq to voltage'
 	 * algorithm.
 	 * When we add voltage scaling, we will also need to do the
 	 * voltage/freq setting in order depending on the direction
 	 * of scaling (like we do in powernow-k7.c)
-	 */
-	case 2:
-		do_powersaver(&longhaul, clock_ratio_index, 3);
-		break;
-
-	/*
-	 * Powersaver. (Nehemiah [C5N])
-	 * As for Ezra-T, we don't do voltage yet.
-	 * This can do FSB scaling too, but it has never been proven
+	 * Nehemiah can do FSB scaling too, but this has never been proven
 	 * to work in practice.
 	 */
-	case 3:
-		do_powersaver(&longhaul, clock_ratio_index, 0xf);
+	case TYPE_POWERSAVER:
+		do_powersaver(&longhaul, clock_ratio_index);
 		break;
 	}
 
@@ -249,7 +286,6 @@
 
 static int __init longhaul_get_ranges(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
 	unsigned long invalue;
 	unsigned int multipliers[32]= {
 		50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
@@ -261,62 +297,66 @@
 	unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 };
 
 	switch (longhaul_version) {
-	case 1:
+	case TYPE_LONGHAUL_V1:
+	case TYPE_LONGHAUL_V2:
 		/* Ugh, Longhaul v1 didn't have the min/max MSRs.
 		   Assume min=3.0x & max = whatever we booted at. */
 		minmult = 30;
 		maxmult = longhaul_get_cpu_mult();
 		rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
 		invalue = (lo & (1<<18|1<<19)) >>18;
-		if (c->x86_model==6)
+		if (cpu_model==CPU_SAMUEL || cpu_model==CPU_SAMUEL2)
 			fsb = eblcr_fsb_table_v1[invalue];
 		else
 			fsb = guess_fsb();
 		break;
 
-	case 2:
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-
-		invalue = longhaul.bits.MaxMHzBR;
-		if (longhaul.bits.MaxMHzBR4)
-			invalue += 16;
-		maxmult=multipliers[invalue];
-
-		invalue = longhaul.bits.MinMHzBR;
-		if (longhaul.bits.MinMHzBR4 == 1)
-			minmult = 30;
-		else
-			minmult = multipliers[invalue];
-
-		fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
-		break;
-
-	case 3:
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-
-		/*
-		 * TODO: This code works, but raises a lot of questions.
-		 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
-		 *   We get around this by using a hardcoded multiplier of 5.0x
-		 *   for the minimimum speed, and the speed we booted up at for the max.
-		 *   This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
-		 * - According to some VIA documentation EBLCR is only
-		 *   in pre-Nehemiah C3s. How this still works is a mystery.
-		 *   We're possibly using something undocumented and unsupported,
-		 *   But it works, so we don't grumble.
-		 */
-		minmult=50;
-		maxmult=longhaul_get_cpu_mult();
-
-		/* Starting with the 1.2GHz parts, theres a 200MHz bus. */
-		if ((cpu_khz/1000) > 1200)
-			fsb = 200;
-		else
+	case TYPE_POWERSAVER:
+		/* Ezra-T */
+		if (cpu_model==CPU_EZRA_T) {
+			rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
+			invalue = longhaul.bits.MaxMHzBR;
+			if (longhaul.bits.MaxMHzBR4)
+				invalue += 16;
+			maxmult=multipliers[invalue];
+
+			invalue = longhaul.bits.MinMHzBR;
+			if (longhaul.bits.MinMHzBR4 == 1)
+				minmult = 30;
+			else
+				minmult = multipliers[invalue];
 			fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
-		break;
+			break;
+		}
+
+		/* Nehemiah */
+		if (cpu_model==CPU_NEHEMIAH) {
+			rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
+
+			/*
+			 * TODO: This code works, but raises a lot of questions.
+			 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
+			 *   We get around this by using a hardcoded multiplier of 4.0x
+			 *   for the minimimum speed, and the speed we booted up at for the max.
+			 *   This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
+			 * - According to some VIA documentation EBLCR is only
+			 *   in pre-Nehemiah C3s. How this still works is a mystery.
+			 *   We're possibly using something undocumented and unsupported,
+			 *   But it works, so we don't grumble.
+			 */
+			minmult=40;
+			maxmult=longhaul_get_cpu_mult();
+
+			/* Starting with the 1.2GHz parts, theres a 200MHz bus. */
+			if ((cpu_khz/1000) > 1200)
+				fsb = 200;
+			else
+				fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
+			break;
+		}
 	}
 
-	dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n",
+	dprintk (KERN_INFO PFX "MinMult:%d.%dx MaxMult:%d.%dx\n",
 		 minmult/10, minmult%10, maxmult/10, maxmult%10);
 
 	if (fsb == -1) {
@@ -324,10 +364,11 @@
 		return -EINVAL;
 	}
 
-	highest_speed = calc_speed (maxmult, fsb);
-	lowest_speed = calc_speed (minmult,fsb);
-	dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n",
-		 fsb, lowest_speed/1000, highest_speed/1000);
+	highest_speed = calc_speed(maxmult);
+	lowest_speed = calc_speed(minmult);
+	dprintk (KERN_INFO PFX "FSB:%dMHz  ", fsb);
+	dprintk ("Lowest speed:%s  ", print_speed(lowest_speed/1000));
+	dprintk ("Highest speed:%s\n", print_speed(highest_speed/1000));
 
 	if (lowest_speed == highest_speed) {
 		printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n");
@@ -350,7 +391,7 @@
 			continue;
 		if (ratio > maxmult || ratio < minmult)
 			continue;
-		longhaul_table[k].frequency = calc_speed (ratio, fsb);
+		longhaul_table[k].frequency = calc_speed(ratio);
 		longhaul_table[k].index	= j;
 		k++;
 	}
@@ -426,8 +467,7 @@
 
 
 static int longhaul_target(struct cpufreq_policy *policy,
-			    unsigned int target_freq,
-			    unsigned int relation)
+			    unsigned int target_freq, unsigned int relation)
 {
 	unsigned int table_index = 0;
 	unsigned int new_clock_ratio = 0;
@@ -442,13 +482,15 @@
 	return 0;
 }
 
+
 static unsigned int longhaul_get(unsigned int cpu)
 {
 	if (cpu)
 		return 0;
-	return (calc_speed (longhaul_get_cpu_mult(), fsb));
+	return calc_speed(longhaul_get_cpu_mult());
 }
 
+
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *c = cpu_data;
@@ -457,26 +499,31 @@
 
 	switch (c->x86_model) {
 	case 6:
+		cpu_model = CPU_SAMUEL;
 		cpuname = "C3 'Samuel' [C5A]";
-		longhaul_version=1;
+		longhaul_version = TYPE_LONGHAUL_V1;
 		memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
 		memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr));
 		break;
 
-	case 7:		/* C5B / C5C */
-		longhaul_version=1;
+	case 7:
+		longhaul_version = TYPE_LONGHAUL_V1;
 		switch (c->x86_mask) {
 		case 0:
+			cpu_model = CPU_SAMUEL2;
 			cpuname = "C3 'Samuel 2' [C5B]";
 			/* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */
 			memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
 			memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr));
 			break;
 		case 1 ... 15:
-			if (c->x86_mask < 8)
+			if (c->x86_mask < 8) {
+				cpu_model = CPU_SAMUEL2;
 				cpuname = "C3 'Samuel 2' [C5B]";
-			else
+			} else {
+				cpu_model = CPU_EZRA;
 				cpuname = "C3 'Ezra' [C5C]";
+			}
 			memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio));
 			memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr));
 			break;
@@ -484,15 +531,17 @@
 		break;
 
 	case 8:
+		cpu_model = CPU_EZRA_T;
 		cpuname = "C3 'Ezra-T' [C5M]";
-		longhaul_version=2;
+		longhaul_version = TYPE_POWERSAVER;
 		numscales=32;
 		memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio));
 		memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr));
 		break;
 
 	case 9:
-		longhaul_version=3;
+		cpu_model = CPU_NEHEMIAH;
+		longhaul_version = TYPE_POWERSAVER;
 		numscales=32;
 		switch (c->x86_mask) {
 		case 0 ... 1:
@@ -518,19 +567,28 @@
 		break;
 	}
 
-	printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n",
-					cpuname, longhaul_version);
+	printk (KERN_INFO PFX "VIA %s CPU detected.  ", cpuname);
+	switch (longhaul_version) {
+	case TYPE_LONGHAUL_V1:
+	case TYPE_LONGHAUL_V2:
+		printk ("Longhaul v%d supported.\n", longhaul_version);
+		break;
+	case TYPE_POWERSAVER:
+		printk ("Powersaver supported.\n");
+		break;
+	};
 
 	ret = longhaul_get_ranges();
 	if (ret != 0)
 		return ret;
 
-	if ((longhaul_version==2) && (dont_scale_voltage==0))
+	if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
+		 (dont_scale_voltage==0))
 		longhaul_setup_voltagescaling();
 
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-	policy->cur = calc_speed (longhaul_get_cpu_mult(), fsb);
+	policy->cur = calc_speed(longhaul_get_cpu_mult());
 
 	ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
 	if (ret)
@@ -563,6 +621,7 @@
 	.attr	= longhaul_attr,
 };
 
+
 static int __init longhaul_init(void)
 {
 	struct cpuinfo_x86 *c = cpu_data;
@@ -580,16 +639,17 @@
 	return -ENODEV;
 }
 
+
 static void __exit longhaul_exit(void)
 {
 	int i=0;
-	unsigned int new_clock_ratio;
-
-	while (clock_ratio[i] != maxmult)
-		i++;
 
-	new_clock_ratio = longhaul_table[i].index & 0xFF;
-	longhaul_setstate(new_clock_ratio);
+	for (i=0; i < numscales; i++) {
+		if (clock_ratio[i] == maxmult) {
+			longhaul_setstate(i);
+			break;
+		}
+	}
 
 	cpufreq_unregister_driver(&longhaul_driver);
 	kfree(longhaul_table);
diff -Nru a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
--- a/arch/i386/kernel/cpu/intel.c	2004-08-22 15:09:07 -07:00
+++ b/arch/i386/kernel/cpu/intel.c	2004-08-24 02:09:07 -07:00
@@ -72,44 +72,44 @@
 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
 static struct _cache_table cache_table[] __initdata =
 {
-	{ 0x06, LVL_1_INST, 8 },
-	{ 0x08, LVL_1_INST, 16 },
-	{ 0x0a, LVL_1_DATA, 8 },
-	{ 0x0c, LVL_1_DATA, 16 },
-	{ 0x22, LVL_3,      512 },
-	{ 0x23, LVL_3,      1024 },
-	{ 0x25, LVL_3,      2048 },
-	{ 0x29, LVL_3,      4096 },
-	{ 0x2c, LVL_1_DATA, 32 },
-	{ 0x30, LVL_1_INST, 32 },
-	{ 0x39, LVL_2,      128 },
-	{ 0x3b, LVL_2,      128 },
-	{ 0x3c, LVL_2,      256 },
-	{ 0x41, LVL_2,      128 },
-	{ 0x42, LVL_2,      256 },
-	{ 0x43, LVL_2,      512 },
-	{ 0x44, LVL_2,      1024 },
-	{ 0x45, LVL_2,      2048 },
-	{ 0x60, LVL_1_DATA, 16 },
-	{ 0x66, LVL_1_DATA, 8 },
-	{ 0x67, LVL_1_DATA, 16 },
-	{ 0x68, LVL_1_DATA, 32 },
-	{ 0x70, LVL_TRACE,  12 },
-	{ 0x71, LVL_TRACE,  16 },
-	{ 0x72, LVL_TRACE,  32 },
-	{ 0x78, LVL_2,	    1024 },
-	{ 0x79, LVL_2,      128 },
-	{ 0x7a, LVL_2,      256 },
-	{ 0x7b, LVL_2,      512 },
-	{ 0x7c, LVL_2,      1024 },
-	{ 0x7d, LVL_2,	    2048 },
-	{ 0x7f, LVL_2,	    512 },
-	{ 0x82, LVL_2,      256 },
-	{ 0x83, LVL_2,      512 },
-	{ 0x84, LVL_2,      1024 },
-	{ 0x85, LVL_2,      2048 },
-	{ 0x86, LVL_2,      512 },
-	{ 0x87, LVL_2,      1024 },
+	{ 0x06, LVL_1_INST, 8 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x08, LVL_1_INST, 16 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x0a, LVL_1_DATA, 8 },	/* 2 way set assoc, 32 byte line size */
+	{ 0x0c, LVL_1_DATA, 16 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x22, LVL_3,      512 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x23, LVL_3,      1024 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x25, LVL_3,      2048 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x29, LVL_3,      4096 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x2c, LVL_1_DATA, 32 },	/* 8-way set assoc, 64 byte line size */
+	{ 0x30, LVL_1_INST, 32 },	/* 8-way set assoc, 64 byte line size */
+	{ 0x39, LVL_2,      128 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x3b, LVL_2,      128 },	/* 2-way set assoc, sectored cache, 64 byte line size */
+	{ 0x3c, LVL_2,      256 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x41, LVL_2,      128 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x42, LVL_2,      256 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x43, LVL_2,      512 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x44, LVL_2,      1024 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x45, LVL_2,      2048 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x60, LVL_1_DATA, 16 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x66, LVL_1_DATA, 8 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x67, LVL_1_DATA, 16 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x68, LVL_1_DATA, 32 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x70, LVL_TRACE,  12 },	/* 8-way set assoc */
+	{ 0x71, LVL_TRACE,  16 },	/* 8-way set assoc */
+	{ 0x72, LVL_TRACE,  32 },	/* 8-way set assoc */
+	{ 0x78, LVL_2,    1024 },	/* 4-way set assoc, 64 byte line size */
+	{ 0x79, LVL_2,     128 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x7a, LVL_2,     256 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x7b, LVL_2,     512 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x7c, LVL_2,    1024 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x7d, LVL_2,    2048 },	/* 8-way set assoc, 64 byte line size */
+	{ 0x7f, LVL_2,     512 },	/* 2-way set assoc, 64 byte line size */
+	{ 0x82, LVL_2,     256 },	/* 8-way set assoc, 32 byte line size */
+	{ 0x83, LVL_2,     512 },	/* 8-way set assoc, 32 byte line size */
+	{ 0x84, LVL_2,    1024 },	/* 8-way set assoc, 32 byte line size */
+	{ 0x85, LVL_2,    2048 },	/* 8-way set assoc, 32 byte line size */
+	{ 0x86, LVL_2,     512 },	/* 4-way set assoc, 64 byte line size */
+	{ 0x87, LVL_2,    1024 },	/* 8-way set assoc, 64 byte line size */
 	{ 0x00, 0, 0}
 };
 
diff -Nru a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
--- a/arch/i386/kernel/cpu/proc.c	2004-06-27 00:19:26 -07:00
+++ b/arch/i386/kernel/cpu/proc.c	2004-08-24 02:08:48 -07:00
@@ -44,8 +44,8 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Intel-defined (#2) */
-		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2",
-		"est", NULL, "cid", NULL, NULL, NULL, NULL, NULL,
+		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est",
+		"tm2", NULL, "cid", NULL, NULL, NULL, "xtpr", NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
diff -Nru a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c
--- a/arch/i386/kernel/doublefault.c	2004-04-12 10:55:02 -07:00
+++ b/arch/i386/kernel/doublefault.c	2004-08-24 02:08:41 -07:00
@@ -13,7 +13,7 @@
 static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
 #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
 
-#define ptr_ok(x) ((x) > 0xc0000000 && (x) < 0xc1000000)
+#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000)
 
 static void doublefault_fn(void)
 {
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	2004-08-23 01:15:00 -07:00
+++ b/arch/i386/kernel/io_apic.c	2004-08-24 02:08:37 -07:00
@@ -1739,7 +1739,7 @@
 		reg_00.raw = io_apic_read(apic, 0);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
-			panic("could not set ID!\n");
+			printk("could not set ID!\n");
 		else
 			apic_printk(APIC_VERBOSE, " ok.\n");
 	}
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	2004-07-28 22:11:30 -07:00
+++ b/arch/i386/kernel/irq.c	2004-08-26 23:30:30 -07:00
@@ -1025,32 +1025,6 @@
 }
 
 #endif
-
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data;
-	unsigned long full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -1086,27 +1060,13 @@
 #endif
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", NULL);
-
-	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-	    return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
-
+	create_prof_cpu_mask(root_irq_dir);
 	/*
 	 * Create entries for all existing IRQs.
 	 */
diff -Nru a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
--- a/arch/i386/kernel/pci-dma.c	2004-03-14 11:17:06 -08:00
+++ b/arch/i386/kernel/pci-dma.c	2004-08-22 17:39:03 -07:00
@@ -13,17 +13,40 @@
 #include <linux/pci.h>
 #include <asm/io.h>
 
+struct dma_coherent_mem {
+	void		*virt_base;
+	u32		device_base;
+	int		size;
+	int		flags;
+	unsigned long	*bitmap;
+};
+
 void *dma_alloc_coherent(struct device *dev, size_t size,
 			   dma_addr_t *dma_handle, int gfp)
 {
 	void *ret;
+	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+	int order = get_order(size);
 	/* ignore region specifiers */
 	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
+	if (mem) {
+		int page = bitmap_find_free_region(mem->bitmap, mem->size,
+						     order);
+		if (page >= 0) {
+			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
+			ret = mem->virt_base + (page << PAGE_SHIFT);
+			memset(ret, 0, size);
+			return ret;
+		}
+		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
+			return NULL;
+	}
+
 	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
 		gfp |= GFP_DMA;
 
-	ret = (void *)__get_free_pages(gfp, get_order(size));
+	ret = (void *)__get_free_pages(gfp, order);
 
 	if (ret != NULL) {
 		memset(ret, 0, size);
@@ -35,5 +58,89 @@
 void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
-	free_pages((unsigned long)vaddr, get_order(size));
+	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+	int order = get_order(size);
+	
+	if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+
+		bitmap_release_region(mem->bitmap, page, order);
+	} else
+		free_pages((unsigned long)vaddr, order);
+}
+
+int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+				dma_addr_t device_addr, size_t size, int flags)
+{
+	void *mem_base;
+	int pages = size >> PAGE_SHIFT;
+	int bitmap_size = (pages + 31)/32;
+
+	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+		goto out;
+	if (!size)
+		goto out;
+	if (dev->dma_mem)
+		goto out;
+
+	/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+
+	mem_base = ioremap(bus_addr, size);
+	if (!mem_base)
+		goto out;
+
+	dev->dma_mem = kmalloc(GFP_KERNEL, sizeof(struct dma_coherent_mem));
+	if (!dev->dma_mem)
+		goto out;
+	memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem));
+	dev->dma_mem->bitmap = kmalloc(GFP_KERNEL, bitmap_size);
+	if (!dev->dma_mem->bitmap)
+		goto free1_out;
+	memset(dev->dma_mem->bitmap, 0, bitmap_size);
+
+	dev->dma_mem->virt_base = mem_base;
+	dev->dma_mem->device_base = device_addr;
+	dev->dma_mem->size = pages;
+	dev->dma_mem->flags = flags;
+
+	if (flags & DMA_MEMORY_MAP)
+		return DMA_MEMORY_MAP;
+
+	return DMA_MEMORY_IO;
+
+ free1_out:
+	kfree(dev->dma_mem->bitmap);
+ out:
+	return 0;
+}
+EXPORT_SYMBOL(dma_declare_coherent_memory);
+
+void dma_release_declared_memory(struct device *dev)
+{
+	struct dma_coherent_mem *mem = dev->dma_mem;
+	
+	if(!mem)
+		return;
+	dev->dma_mem = NULL;
+	kfree(mem->bitmap);
+	kfree(mem);
+}
+EXPORT_SYMBOL(dma_release_declared_memory);
+
+void *dma_mark_declared_memory_occupied(struct device *dev,
+					dma_addr_t device_addr, size_t size)
+{
+	struct dma_coherent_mem *mem = dev->dma_mem;
+	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	int pos, err;
+
+	if (!mem)
+		return ERR_PTR(-EINVAL);
+
+	pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
+	err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
+	if (err != 0)
+		return ERR_PTR(err);
+	return mem->virt_base + (pos << PAGE_SHIFT);
 }
+EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	2004-08-23 01:14:52 -07:00
+++ b/arch/i386/kernel/process.c	2004-08-24 02:08:44 -07:00
@@ -183,18 +183,13 @@
 		printk("monitor/mwait feature present.\n");
 		/*
 		 * Skip, if setup has overridden idle.
-		 * Also, take care of system with asymmetric CPUs.
-		 * Use, mwait_idle only if all cpus support it.
-		 * If not, we fallback to default_idle()
+		 * One CPU supports mwait => All CPUs supports mwait
 		 */
 		if (!pm_idle) {
 			printk("using mwait in idle threads.\n");
 			pm_idle = mwait_idle;
 		}
-		return;
 	}
-	pm_idle = default_idle;
-	return;
 }
 
 static int __init idle_setup (char *str)
@@ -595,7 +590,7 @@
 	child_tidptr = (int __user *)regs.edi;
 	if (!newsp)
 		newsp = regs.esp;
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, parent_tidptr, child_tidptr);
+	return do_fork(clone_flags, newsp, &regs, 0, parent_tidptr, child_tidptr);
 }
 
 /*
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	2004-07-13 13:49:37 -07:00
+++ b/arch/i386/kernel/setup.c	2004-08-26 23:59:59 -07:00
@@ -219,9 +219,14 @@
 	.end	= 0x0021,
 	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
 }, {
-	.name	= "timer",
+	.name   = "timer0",
 	.start	= 0x0040,
-	.end	= 0x005f,
+	.end    = 0x0043,
+	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name   = "timer1",
+	.start  = 0x0050,
+	.end    = 0x0053,
 	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
 }, {
 	.name	= "keyboard",
diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
--- a/arch/i386/kernel/signal.c	2004-07-13 05:53:49 -07:00
+++ b/arch/i386/kernel/signal.c	2004-08-25 10:13:40 -07:00
@@ -411,9 +411,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -492,9 +490,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -502,11 +498,9 @@
  */	
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+	      sigset_t *oldset,	struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Are we from a system call? */
 	if (regs->orig_eax >= 0) {
 		/* If so, check system call restarting.. */
@@ -534,9 +528,6 @@
 	else
 		setup_frame(sig, ka, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -555,6 +546,7 @@
 {
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -573,7 +565,7 @@
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Reenable any watchpoints before delivering the
 		 * signal to user space. The processor register will
@@ -583,7 +575,7 @@
 		__asm__("movl %0,%%db7"	: : "r" (current->thread.debugreg[7]));
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &info, &ka, oldset, regs);
 		return 1;
 	}
 
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c	2004-08-22 15:18:01 -07:00
+++ b/arch/i386/kernel/smpboot.c	2004-08-25 12:43:26 -07:00
@@ -496,16 +496,6 @@
 	unsigned short ss;
 } stack_start;
 
-static struct task_struct * __init fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/*
-	 * don't care about the eip and regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 #ifdef CONFIG_NUMA
 
 /* which logical CPUs are on which nodes */
@@ -801,21 +791,10 @@
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
 	 */
-	idle = fork_by_hand();
+	idle = fork_idle(cpu);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpu);
-	wake_up_forked_process(idle);
-
-	/*
-	 * We remove it from the pidhash and the runqueue
-	 * once we got the process:
-	 */
-	init_idle(idle, cpu);
-
 	idle->thread.eip = (unsigned long) start_secondary;
-
-	unhash_process(idle);
-
 	/* start_eip had better be page-aligned! */
 	start_eip = setup_trampoline();
 
@@ -1137,213 +1116,6 @@
 	if (cpu_has_tsc && cpucount && cpu_khz)
 		synchronize_tsc_bp();
 }
-
-#ifdef CONFIG_SCHED_SMT
-#ifdef CONFIG_NUMA
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-		struct sched_domain *node_domain = &per_cpu(node_domains, i);
-		int node = cpu_to_node(i);
-		cpumask_t nodemask = node_to_cpumask(node);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		cpu_domain->span = cpu_sibling_map[i];
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = nodemask;
-		phys_domain->parent = node_domain;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-
-		*node_domain = SD_NODE_INIT;
-		node_domain->span = cpu_possible_map;
-		node_domain->groups = &sched_group_nodes[cpu_to_node(i)];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpu->cpumask = CPU_MASK_NONE;
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		int j;
-		cpumask_t nodemask;
-		struct sched_group *node = &sched_group_nodes[i];
-		cpumask_t node_cpumask = node_to_cpumask(i);
-
-		cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-		if (cpus_empty(nodemask))
-			continue;
-
-		first = last = NULL;
-		/* Set up physical groups */
-		for_each_cpu_mask(j, nodemask) {
-			struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j);
-			struct sched_group *cpu = &sched_group_phys[j];
-
-			if (j != first_cpu(cpu_domain->span))
-				continue;
-
-			cpu->cpumask = cpu_domain->span;
-			/*
-			 * Make each extra sibling increase power by 10% of
-			 * the basic CPU. This is very arbitrary.
-			 */
-			cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-			node->cpu_power += cpu->cpu_power;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	/* Set up nodes */
-	first = last = NULL;
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		struct sched_group *cpu = &sched_group_nodes[i];
-		cpumask_t nodemask;
-		cpumask_t node_cpumask = node_to_cpumask(i);
-
-		cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-		if (cpus_empty(nodemask))
-			continue;
-
-		cpu->cpumask = nodemask;
-		/* ->cpu_power already setup */
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
-}
-#else /* !CONFIG_NUMA */
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		cpu_domain->span = cpu_sibling_map[i];
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = cpu_possible_map;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	first = last = NULL;
-	/* Set up physical groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_group *cpu = &sched_group_phys[i];
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		cpu->cpumask = cpu_domain->span;
-		/* See SMT+NUMA setup for comment */
-		cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
-}
-#endif /* CONFIG_NUMA */
-#endif /* CONFIG_SCHED_SMT */
 
 /* These are wrappers to interface to the new boot process.  Someone
    who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
diff -Nru a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
--- a/arch/i386/kernel/sysenter.c	2004-08-23 01:14:52 -07:00
+++ b/arch/i386/kernel/sysenter.c	2004-08-26 23:59:59 -07:00
@@ -43,18 +43,18 @@
 
 static int __init sysenter_setup(void)
 {
-	unsigned long page = get_zeroed_page(GFP_ATOMIC);
+	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
 
 	__set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
 
 	if (!boot_cpu_has(X86_FEATURE_SEP)) {
-		memcpy((void *) page,
+		memcpy(page,
 		       &vsyscall_int80_start,
 		       &vsyscall_int80_end - &vsyscall_int80_start);
 		return 0;
 	}
 
-	memcpy((void *) page,
+	memcpy(page,
 	       &vsyscall_sysenter_start,
 	       &vsyscall_sysenter_end - &vsyscall_sysenter_start);
 
diff -Nru a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
--- a/arch/i386/kernel/vmlinux.lds.S	2004-04-12 10:55:00 -07:00
+++ b/arch/i386/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -4,6 +4,7 @@
 
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
+#include <asm/page.h>
 
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
@@ -11,7 +12,7 @@
 jiffies = jiffies_64;
 SECTIONS
 {
-  . = 0xC0000000 + 0x100000;
+  . = __PAGE_OFFSET + 0x100000;
   /* read-only */
   _text = .;			/* Text and read-only data */
   .text : {
@@ -66,9 +67,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff -Nru a/arch/i386/kernel/vsyscall.lds b/arch/i386/kernel/vsyscall.lds
--- a/arch/i386/kernel/vsyscall.lds	2003-04-23 13:59:12 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,67 +0,0 @@
-/*
- * Linker script for vsyscall DSO.  The vsyscall page is an ELF shared
- * object prelinked to its virtual address, and with only one read-only
- * segment (that fits in one page).  This script controls its layout.
- */
-
-/* This must match <asm/fixmap.h>.  */
-VSYSCALL_BASE = 0xffffe000;
-
-SECTIONS
-{
-  . = VSYSCALL_BASE + SIZEOF_HEADERS;
-
-  .hash           : { *(.hash) }		:text
-  .dynsym         : { *(.dynsym) }
-  .dynstr         : { *(.dynstr) }
-  .gnu.version    : { *(.gnu.version) }
-  .gnu.version_d  : { *(.gnu.version_d) }
-  .gnu.version_r  : { *(.gnu.version_r) }
-
-  /* This linker script is used both with -r and with -shared.
-     For the layouts to match, we need to skip more than enough
-     space for the dynamic symbol table et al.  If this amount
-     is insufficient, ld -shared will barf.  Just increase it here.  */
-  . = VSYSCALL_BASE + 0x400;
-
-  .text           : { *(.text) }		:text =0x90909090
-
-  .eh_frame_hdr   : { *(.eh_frame_hdr) }	:text :eh_frame_hdr
-  .eh_frame       : { KEEP (*(.eh_frame)) }	:text
-  .dynamic        : { *(.dynamic) }		:text :dynamic
-  .useless        : {
-  	*(.got.plt) *(.got)
-	*(.data .data.* .gnu.linkonce.d.*)
-	*(.dynbss)
-	*(.bss .bss.* .gnu.linkonce.b.*)
-  }						:text
-}
-
-/*
- * We must supply the ELF program headers explicitly to get just one
- * PT_LOAD segment, and set the flags explicitly to make segments read-only.
- */
-PHDRS
-{
-  text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
-  dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
-  eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
-}
-
-/*
- * This controls what symbols we export from the DSO.
- */
-VERSION
-{
-  LINUX_2.5 {
-    global:
-    	__kernel_vsyscall;
-    	__kernel_sigreturn;
-    	__kernel_rt_sigreturn;
-
-    local: *;
-  };
-}
-
-/* The ELF entry point can be used to set the AT_SYSINFO value.  */
-ENTRY(__kernel_vsyscall);
diff -Nru a/arch/i386/kernel/vsyscall.lds.S b/arch/i386/kernel/vsyscall.lds.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/i386/kernel/vsyscall.lds.S	2004-08-24 02:08:54 -07:00
@@ -0,0 +1,67 @@
+/*
+ * Linker script for vsyscall DSO.  The vsyscall page is an ELF shared
+ * object prelinked to its virtual address, and with only one read-only
+ * segment (that fits in one page).  This script controls its layout.
+ */
+#include <asm/fixmap.h>
+
+VSYSCALL_BASE = __FIXADDR_TOP - 0x1000;
+
+SECTIONS
+{
+  . = VSYSCALL_BASE + SIZEOF_HEADERS;
+
+  .hash           : { *(.hash) }		:text
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+
+  /* This linker script is used both with -r and with -shared.
+     For the layouts to match, we need to skip more than enough
+     space for the dynamic symbol table et al.  If this amount
+     is insufficient, ld -shared will barf.  Just increase it here.  */
+  . = VSYSCALL_BASE + 0x400;
+
+  .text           : { *(.text) }		:text =0x90909090
+
+  .eh_frame_hdr   : { *(.eh_frame_hdr) }	:text :eh_frame_hdr
+  .eh_frame       : { KEEP (*(.eh_frame)) }	:text
+  .dynamic        : { *(.dynamic) }		:text :dynamic
+  .useless        : {
+  	*(.got.plt) *(.got)
+	*(.data .data.* .gnu.linkonce.d.*)
+	*(.dynbss)
+	*(.bss .bss.* .gnu.linkonce.b.*)
+  }						:text
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+  text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+  eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+  LINUX_2.5 {
+    global:
+    	__kernel_vsyscall;
+    	__kernel_sigreturn;
+    	__kernel_rt_sigreturn;
+
+    local: *;
+  };
+}
+
+/* The ELF entry point can be used to set the AT_SYSINFO value.  */
+ENTRY(__kernel_vsyscall);
diff -Nru a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
--- a/arch/i386/lib/usercopy.c	2004-06-29 07:44:49 -07:00
+++ b/arch/i386/lib/usercopy.c	2004-08-26 23:31:38 -07:00
@@ -31,6 +31,7 @@
 #define __do_strncpy_from_user(dst,src,count,res)			   \
 do {									   \
 	int __d0, __d1, __d2;						   \
+	might_sleep();							   \
 	__asm__ __volatile__(						   \
 		"	testl %1,%1\n"					   \
 		"	jz 2f\n"					   \
@@ -119,6 +120,7 @@
 #define __do_clear_user(addr,size)					\
 do {									\
 	int __d0;							\
+	might_sleep();							\
   	__asm__ __volatile__(						\
 		"0:	rep; stosl\n"					\
 		"	movl %2,%0\n"					\
diff -Nru a/arch/i386/mach-es7000/es7000.h b/arch/i386/mach-es7000/es7000.h
--- a/arch/i386/mach-es7000/es7000.h	2004-05-10 04:25:50 -07:00
+++ b/arch/i386/mach-es7000/es7000.h	2004-08-24 02:08:46 -07:00
@@ -29,7 +29,7 @@
 
 #define	MIP_BUSY		1
 #define	MIP_SPIN		0xf0000
-#define	MIP_VALID		0x0100000000000000
+#define	MIP_VALID		0x0100000000000000ULL
 #define	MIP_PORT(VALUE)	((VALUE >> 32) & 0xffff)
 
 #define	MIP_RD_LO(VALUE)	(VALUE & 0xffffffff)   
diff -Nru a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
--- a/arch/i386/mach-es7000/es7000plat.c	2004-06-12 20:52:27 -07:00
+++ b/arch/i386/mach-es7000/es7000plat.c	2004-08-24 02:08:46 -07:00
@@ -237,7 +237,7 @@
 	}
 
 	status = ((unsigned long long)mip_reg->off_0 &
-		(unsigned long long)0xffff0000000000) >> 48;
+		(unsigned long long)0xffff0000000000ULL) >> 48;
 	mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 &
 		(unsigned long long)~MIP_VALID);
 	return status;
diff -Nru a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c
--- a/arch/i386/mach-generic/bigsmp.c	2003-08-18 19:46:23 -07:00
+++ b/arch/i386/mach-generic/bigsmp.c	2004-08-24 02:08:37 -07:00
@@ -13,15 +13,41 @@
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/dmi.h>
 #include <asm/mach-bigsmp/mach_apic.h>
 #include <asm/mach-bigsmp/mach_apicdef.h>
 #include <asm/mach-bigsmp/mach_ipi.h>
 #include <asm/mach-default/mach_mpparse.h>
 
-int dmi_bigsmp; /* can be set by dmi scanners */
+static int dmi_bigsmp; /* can be set by dmi scanners */
+
+static __init int hp_ht_bigsmp(struct dmi_system_id *d)
+{
+#ifdef CONFIG_X86_GENERICARCH
+	printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
+	dmi_bigsmp = 1;
+#endif
+	return 0;
+}
+
+
+static struct dmi_system_id __initdata bigsmp_dmi_table[] = {
+	{ hp_ht_bigsmp, "HP ProLiant DL760 G2", {
+		DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+		DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
+	}},
+
+	{ hp_ht_bigsmp, "HP ProLiant DL740", {
+		DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+		DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
+	 }},
+	 { }
+};
+
 
 static __init int probe_bigsmp(void)
 { 
+	dmi_check_system(bigsmp_dmi_table);
 	return dmi_bigsmp; 
 } 
 
diff -Nru a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
--- a/arch/i386/mach-voyager/voyager_smp.c	2004-08-23 01:14:52 -07:00
+++ b/arch/i386/mach-voyager/voyager_smp.c	2004-08-26 23:30:31 -07:00
@@ -523,15 +523,6 @@
 	return cpu_idle();
 }
 
-static struct task_struct * __init
-fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/* don't care about the eip and regs settings since we'll
-	 * never reschedule the forked task. */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 
 /* Routine to kick start the given CPU and wait for it to report ready
  * (or timeout in startup).  When this routine returns, the requested
@@ -587,16 +578,10 @@
 	hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF;
 
 	cpucount++;
-	idle = fork_by_hand();
+	idle = fork_idle(cpu);
 	if(IS_ERR(idle))
 		panic("failed fork for CPU%d", cpu);
-
-	wake_up_forked_process(idle);
-
-	init_idle(idle, cpu);
-
 	idle->thread.eip = (unsigned long) start_secondary;
-	unhash_process(idle);
 	/* init_tasks (in sched.c) is indexed logically */
 	stack_start.esp = (void *) idle->thread.esp;
 
@@ -1302,8 +1287,7 @@
 	int cpu = smp_processor_id();
 	long weight;
 
-	x86_do_profile(regs);
-
+	profile_tick(CPU_PROFILING, regs);
 	if (--per_cpu(prof_counter, cpu) <= 0) {
 		/*
 		 * The multiplier may have changed since the last time we got
diff -Nru a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
--- a/arch/i386/mm/Makefile	2003-02-24 23:13:13 -08:00
+++ b/arch/i386/mm/Makefile	2004-08-24 02:08:15 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the linux i386-specific parts of the memory manager.
 #
 
-obj-y	:= init.o pgtable.o fault.o ioremap.o extable.o pageattr.o 
+obj-y	:= init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o
 
 obj-$(CONFIG_DISCONTIGMEM)	+= discontig.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
--- a/arch/i386/mm/discontig.c	2004-07-26 13:47:15 -07:00
+++ b/arch/i386/mm/discontig.c	2004-08-24 02:08:33 -07:00
@@ -417,15 +417,15 @@
 		 * remapped KVA area - mbligh
 		 */
 		if (!nid)
-			free_area_init_node(nid, NODE_DATA(nid), 0, 
-				zones_size, start, zholes_size);
+			free_area_init_node(nid, NODE_DATA(nid),
+					zones_size, start, zholes_size);
 		else {
 			unsigned long lmem_map;
 			lmem_map = (unsigned long)node_remap_start_vaddr[nid];
 			lmem_map += sizeof(pg_data_t) + PAGE_SIZE - 1;
 			lmem_map &= PAGE_MASK;
-			free_area_init_node(nid, NODE_DATA(nid), 
-				(struct page *)lmem_map, zones_size, 
+			NODE_DATA(nid)->node_mem_map = (struct page *)lmem_map;
+			free_area_init_node(nid, NODE_DATA(nid), zones_size,
 				start, zholes_size);
 		}
 	}
diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
--- a/arch/i386/mm/fault.c	2004-08-23 01:14:51 -07:00
+++ b/arch/i386/mm/fault.c	2004-08-26 23:59:59 -07:00
@@ -513,12 +513,13 @@
 		 * an interrupt in the middle of a task switch..
 		 */
 		int index = pgd_index(address);
+		unsigned long pgd_paddr;
 		pgd_t *pgd, *pgd_k;
 		pmd_t *pmd, *pmd_k;
 		pte_t *pte_k;
 
-		asm("movl %%cr3,%0":"=r" (pgd));
-		pgd = index + (pgd_t *)__va(pgd);
+		asm("movl %%cr3,%0":"=r" (pgd_paddr));
+		pgd = index + (pgd_t *)__va(pgd_paddr);
 		pgd_k = init_mm.pgd + index;
 
 		if (!pgd_present(*pgd_k))
diff -Nru a/arch/i386/mm/mmap.c b/arch/i386/mm/mmap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/i386/mm/mmap.c	2004-08-24 02:08:15 -07:00
@@ -0,0 +1,71 @@
+/*
+ *  linux/arch/i386/mm/mmap.c
+ *
+ *  flexible mmap layout support
+ *
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * Started by Ingo Molnar <mingo@elte.hu>
+ */
+
+#include <linux/personality.h>
+#include <linux/mm.h>
+
+/*
+ * Top of mmap area (just below the process stack).
+ *
+ * Leave an at least ~128 MB hole.
+ */
+#define MIN_GAP (128*1024*1024)
+#define MAX_GAP (TASK_SIZE/6*5)
+
+static inline unsigned long mmap_base(struct mm_struct *mm)
+{
+	unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur;
+
+	if (gap < MIN_GAP)
+		gap = MIN_GAP;
+	else if (gap > MAX_GAP)
+		gap = MAX_GAP;
+
+	return TASK_SIZE - (gap & PAGE_MASK);
+}
+
+/*
+ * This function, called very early during the creation of a new
+ * process VM image, sets up which VM layout function to use:
+ */
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	/*
+	 * Fall back to the standard layout if the personality
+	 * bit is set, or if the expected stack growth is unlimited:
+	 */
+	if (sysctl_legacy_va_layout ||
+			(current->personality & ADDR_COMPAT_LAYOUT) ||
+			current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
+		mm->mmap_base = TASK_UNMAPPED_BASE;
+		mm->get_unmapped_area = arch_get_unmapped_area;
+		mm->unmap_area = arch_unmap_area;
+	} else {
+		mm->mmap_base = mmap_base(mm);
+		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+		mm->unmap_area = arch_unmap_area_topdown;
+	}
+}
diff -Nru a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
--- a/arch/i386/mm/pageattr.c	2004-06-30 17:00:00 -07:00
+++ b/arch/i386/mm/pageattr.c	2004-08-26 23:59:59 -07:00
@@ -114,7 +114,7 @@
 	kpte = lookup_address(address);
 	if (!kpte)
 		return -EINVAL;
-	kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
+	kpte_page = virt_to_page(kpte);
 	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { 
 		if ((pte_val(*kpte) & _PAGE_PSE) == 0) { 
 			pte_t old = *kpte;
diff -Nru a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
--- a/arch/i386/pci/i386.c	2003-07-31 16:47:19 -07:00
+++ b/arch/i386/pci/i386.c	2004-08-24 23:35:30 -07:00
@@ -142,7 +142,7 @@
 				DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
 				    r->start, r->end, r->flags, disabled, pass);
 				pr = pci_find_parent_resource(dev, r);
-				if (!pr || request_resource(pr, r) < 0) {
+				if (!pr || insert_resource(pr, r) < 0) {
 					printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev));
 					/* We'll assign a new address later */
 					r->end -= r->start;
diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
--- a/arch/ia64/hp/sim/simserial.c	2004-04-12 10:54:30 -07:00
+++ b/arch/ia64/hp/sim/simserial.c	2004-08-24 02:08:52 -07:00
@@ -1055,7 +1055,7 @@
 			ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq);
 		}
 
-		printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n",
+		printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n",
 		       state->line,
 		       state->port, state->irq,
 		       uart_config[state->type].name);
diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
--- a/arch/ia64/ia32/binfmt_elf32.c	2004-07-26 22:26:50 -07:00
+++ b/arch/ia64/ia32/binfmt_elf32.c	2004-08-27 00:02:34 -07:00
@@ -187,7 +187,7 @@
 		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)?
 					PAGE_COPY_EXEC: PAGE_COPY;
 		insert_vm_struct(current->mm, mpnt);
-		current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+		current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt);
 	}
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S	2004-07-28 10:57:03 -07:00
+++ b/arch/ia64/ia32/ia32_entry.S	2004-08-24 02:08:42 -07:00
@@ -41,7 +41,7 @@
 	zxt4 out1=in1				// newsp
 	mov out3=16				// stacksize (compensates for 16-byte scratch area)
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
-	dep out0=0,in0,CLONE_IDLETASK_BIT,1	// out0 = clone_flags & ~CLONE_IDLETASK
+	mov out0=in0				// out0 = clone_flags
 	zxt4 out4=in2				// out4 = parent_tidptr
 	zxt4 out5=in4				// out5 = child_tidptr
 	br.call.sptk.many rp=do_fork
diff -Nru a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
--- a/arch/ia64/ia32/ia32_signal.c	2004-05-10 23:44:41 -07:00
+++ b/arch/ia64/ia32/ia32_signal.c	2004-08-25 17:37:25 -07:00
@@ -882,9 +882,7 @@
 	return 1;
 
   give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return 0;
 }
 
@@ -952,9 +950,7 @@
 	return 1;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return 0;
 }
 
diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
--- a/arch/ia64/ia32/ia32_support.c	2004-06-16 18:09:33 -07:00
+++ b/arch/ia64/ia32/ia32_support.c	2004-08-18 10:25:15 -07:00
@@ -145,6 +145,9 @@
 	int cpu = smp_processor_id();
 
 	ia32_shared_page[cpu] = alloc_page(GFP_KERNEL);
+	if (!ia32_shared_page[cpu])
+		panic("failed to allocate ia32_shared_page[%d]\n", cpu);
+
 	cpu_gdt_table[cpu] = page_address(ia32_shared_page[cpu]);
 
 	/* Copy from the boot cpu's GDT */
@@ -161,6 +164,9 @@
 	unsigned long ldt_size;
 
 	ia32_shared_page[0] = alloc_page(GFP_KERNEL);
+	if (!ia32_shared_page[0])
+		panic("failed to allocate ia32_shared_page[0]\n");
+
 	ia32_boot_gdt = page_address(ia32_shared_page[0]);
 	cpu_gdt_table[0] = ia32_boot_gdt;
 
diff -Nru a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
--- a/arch/ia64/kernel/asm-offsets.c	2003-12-18 09:47:18 -08:00
+++ b/arch/ia64/kernel/asm-offsets.c	2004-08-24 02:08:42 -07:00
@@ -195,11 +195,6 @@
 	DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 
 
-	DEFINE(CLONE_IDLETASK_BIT, 12);
-#if CLONE_IDLETASK != (1 << 12)
-# error "CLONE_IDLETASK_BIT incorrect, please fix"
-#endif
-
 	DEFINE(CLONE_SETTLS_BIT, 19);
 #if CLONE_SETTLS != (1<<19)
 # error "CLONE_SETTLS_BIT incorrect, please fix"
diff -Nru a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
--- a/arch/ia64/kernel/cyclone.c	2004-08-03 16:19:50 -07:00
+++ b/arch/ia64/kernel/cyclone.c	2004-08-18 11:10:33 -07:00
@@ -1,6 +1,8 @@
+#include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/errno.h>
+#include <asm/io.h>
 
 /* IBM Summit (EXA) Cyclone counter code*/
 #define CYCLONE_CBAR_ADDR 0xFEB00CD0
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	2004-07-07 11:11:34 -07:00
+++ b/arch/ia64/kernel/entry.S	2004-08-24 02:08:42 -07:00
@@ -128,7 +128,7 @@
 (p6)	st8 [r2]=in5				// store TLS in r16 for copy_thread()
 	mov out5=in4	// child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
-	dep out0=0,in0,CLONE_IDLETASK_BIT,1	// out0 = clone_flags & ~CLONE_IDLETASK
+	mov out0=in0				// out0 = clone_flags
 	br.call.sptk.many rp=do_fork
 .ret1:	.restore sp
 	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
@@ -157,7 +157,7 @@
 (p6)	st8 [r2]=in4				// store TLS in r13 (tp)
 	mov out5=in3	// child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
-	dep out0=0,in0,CLONE_IDLETASK_BIT,1	// out0 = clone_flags & ~CLONE_IDLETASK
+	mov out0=in0				// out0 = clone_flags
 	br.call.sptk.many rp=do_fork
 .ret2:	.restore sp
 	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
--- a/arch/ia64/kernel/head.S	2004-06-28 15:11:32 -07:00
+++ b/arch/ia64/kernel/head.S	2004-08-18 11:17:23 -07:00
@@ -781,8 +781,7 @@
 
 	// going to virtual
 	//   - for code addresses, set upper bits of addr to KERNEL_START
-	//   - for stack addresses, set upper 3 bits to 0xe.... Dont change any of the
-	//     lower bits since we want it to stay identity mapped
+	//   - for stack addresses, copy from input argument
 	movl r18=KERNEL_START
 	dep r3=0,r3,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
 	dep r14=0,r14,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	2004-07-26 16:37:18 -07:00
+++ b/arch/ia64/kernel/irq.c	2004-08-26 23:30:30 -07:00
@@ -1137,31 +1137,6 @@
 }
 #endif
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data;
-	unsigned long full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -1196,26 +1171,15 @@
 #endif
 }
 
-cpumask_t prof_cpu_mask = CPU_MASK_ALL;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", 0);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-		return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	2004-08-08 14:07:46 -07:00
+++ b/arch/ia64/kernel/perfmon.c	2004-08-27 00:02:34 -07:00
@@ -2352,7 +2352,7 @@
 	insert_vm_struct(mm, vma);
 
 	mm->total_vm  += size >> PAGE_SHIFT;
-
+	vm_stat_account(vma);
 	up_write(&task->mm->mmap_sem);
 
 	/*
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	2004-05-10 23:44:41 -07:00
+++ b/arch/ia64/kernel/signal.c	2004-08-25 10:13:41 -07:00
@@ -1,7 +1,7 @@
 /*
  * Architecture-specific signal handling support.
  *
- * Copyright (C) 1999-2003 Hewlett-Packard Co
+ * Copyright (C) 1999-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Derived from i386 and Alpha versions.
@@ -352,13 +352,42 @@
 }
 
 static long
+force_sigsegv_info (int sig, void *addr)
+{
+	unsigned long flags;
+	struct siginfo si;
+
+	if (sig == SIGSEGV) {
+		/*
+		 * Acquiring siglock around the sa_handler-update is almost
+		 * certainly overkill, but this isn't a
+		 * performance-critical path and I'd rather play it safe
+		 * here than having to debug a nasty race if and when
+		 * something changes in kernel/signal.c that would make it
+		 * no longer safe to modify sa_handler without holding the
+		 * lock.
+		 */
+		spin_lock_irqsave(&current->sighand->siglock, flags);
+		current->sighand->action[sig - 1].sa.sa_handler = SIG_DFL;
+		spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	}
+	si.si_signo = SIGSEGV;
+	si.si_errno = 0;
+	si.si_code = SI_KERNEL;
+	si.si_pid = current->pid;
+	si.si_uid = current->uid;
+	si.si_addr = addr;
+	force_sig_info(SIGSEGV, &si, current);
+	return 0;
+}
+
+static long
 setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
 	     struct sigscratch *scr)
 {
 	extern char __kernel_sigtramp[];
 	unsigned long tramp_addr, new_rbs = 0;
 	struct sigframe *frame;
-	struct siginfo si;
 	long err;
 
 	frame = (void *) scr->pt.r12;
@@ -377,7 +406,7 @@
 	frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return force_sigsegv_info(sig, frame);
 
 	err  = __put_user(sig, &frame->arg0);
 	err |= __put_user(&frame->info, &frame->arg1);
@@ -393,8 +422,8 @@
 	err |= __put_user(sas_ss_flags(scr->pt.r12), &frame->sc.sc_stack.ss_flags);
 	err |= setup_sigcontext(&frame->sc, set, scr);
 
-	if (err)
-		goto give_sigsegv;
+	if (unlikely(err))
+		return force_sigsegv_info(sig, frame);
 
 	scr->pt.r12 = (unsigned long) frame - 16;	/* new stack pointer */
 	scr->pt.ar_fpsr = FPSR_DEFAULT;			/* reset fpsr for signal handler */
@@ -422,18 +451,6 @@
 	       current->comm, current->pid, sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
 #endif
 	return 1;
-
-  give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	si.si_signo = SIGSEGV;
-	si.si_errno = 0;
-	si.si_code = SI_KERNEL;
-	si.si_pid = current->pid;
-	si.si_uid = current->uid;
-	si.si_addr = frame;
-	force_sig_info(SIGSEGV, &si, current);
-	return 0;
 }
 
 static long
@@ -449,9 +466,6 @@
 		if (!setup_frame(sig, ka, info, oldset, scr))
 			return 0;
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		{
@@ -471,7 +485,7 @@
 long
 ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
 {
-	struct k_sigaction *ka;
+	struct k_sigaction ka;
 	siginfo_t info;
 	long restart = in_syscall;
 	long errno = scr->pt.r8;
@@ -493,7 +507,7 @@
 	 * need to push through a forced SIGSEGV.
 	 */
 	while (1) {
-		int signr = get_signal_to_deliver(&info, &scr->pt, NULL);
+		int signr = get_signal_to_deliver(&info, &ka, &scr->pt, NULL);
 
 		/*
 		 * get_signal_to_deliver() may have run a debugger (via notify_parent())
@@ -520,8 +534,6 @@
 		if (signr <= 0)
 			break;
 
-		ka = &current->sighand->action[signr - 1];
-
 		if (unlikely(restart)) {
 			switch (errno) {
 			      case ERESTART_RESTARTBLOCK:
@@ -531,7 +543,7 @@
 				break;
 
 			      case ERESTARTSYS:
-				if ((ka->sa.sa_flags & SA_RESTART) == 0) {
+				if ((ka.sa.sa_flags & SA_RESTART) == 0) {
 					scr->pt.r8 = ERR_CODE(EINTR);
 					/* note: scr->pt.r10 is already -1 */
 					break;
@@ -550,7 +562,7 @@
 		 * Whee!  Actually deliver the signal.  If the delivery failed, we need to
 		 * continue to iterate in this loop so we can deliver the SIGSEGV...
 		 */
-		if (handle_signal(signr, ka, &info, oldset, scr))
+		if (handle_signal(signr, &ka, &info, oldset, scr))
 			return 1;
 	}
 
diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
--- a/arch/ia64/kernel/smpboot.c	2004-08-04 10:50:16 -07:00
+++ b/arch/ia64/kernel/smpboot.c	2004-08-24 02:08:43 -07:00
@@ -356,19 +356,15 @@
 	return cpu_idle();
 }
 
-static struct task_struct * __devinit
-fork_by_hand (void)
+struct pt_regs * __init idle_regs(struct pt_regs *regs)
 {
-	/*
-	 * Don't care about the IP and regs settings since we'll never reschedule the
-	 * forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL, NULL);
+	return NULL;
 }
 
 struct create_idle {
 	struct task_struct *idle;
 	struct completion done;
+	int cpu;
 };
 
 void
@@ -376,7 +372,7 @@
 {
 	struct create_idle *c_idle = _c_idle;
 
-	c_idle->idle = fork_by_hand();
+	c_idle->idle = fork_idle(c_idle->cpu);
 	complete(&c_idle->done);
 }
 
@@ -384,10 +380,11 @@
 do_boot_cpu (int sapicid, int cpu)
 {
 	int timeout;
-	struct create_idle c_idle;
+	struct create_idle c_idle = {
+		.cpu	= cpu,
+		.done	= COMPLETION_INITIALIZER(c_idle.done),
+	};
 	DECLARE_WORK(work, do_fork_idle, &c_idle);
-
-	init_completion(&c_idle.done);
 	/*
 	 * We can't use kernel_thread since we must avoid to reschedule the child.
 	 */
@@ -400,16 +397,6 @@
 
 	if (IS_ERR(c_idle.idle))
 		panic("failed fork for CPU %d", cpu);
-	wake_up_forked_process(c_idle.idle);
-
-	/*
-	 * We remove it from the pidhash and the runqueue
-	 * once we got the process:
-	 */
-	init_idle(c_idle.idle, cpu);
-
-	unhash_process(c_idle.idle);
-
 	task_for_booting_cpu = c_idle.idle;
 
 	Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
@@ -719,3 +706,4 @@
 		printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n",
 		       ia64_sal_strerror(sal_ret));
 }
+
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	2004-06-04 15:44:03 -07:00
+++ b/arch/ia64/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -186,52 +186,6 @@
 
 EXPORT_SYMBOL(do_gettimeofday);
 
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void
-ia64_do_profile (struct pt_regs * regs)
-{
-	unsigned long ip, slot;
-	extern cpumask_t prof_cpu_mask;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	ip = instruction_pointer(regs);
-	/* Conserve space in histogram by encoding slot bits in address
-	 * bits 2 and 3 rather than bits 0 and 1.
-	 */
-	slot = ip & 3;
-	ip = (ip & ~3UL) + 4*slot;
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!cpu_isset(smp_processor_id(), prof_cpu_mask))
-		return;
-
-	ip -= (unsigned long) &_stext;
-	ip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds IP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (ip > prof_len-1)
-		ip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[ip]);
-}
-
 static irqreturn_t
 timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -249,7 +203,7 @@
 		printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
 		       ia64_get_itc(), new_itm);
 
-	ia64_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 
 	while (1) {
 #ifdef CONFIG_SMP
@@ -371,7 +325,7 @@
 		itc_drift = -1;
 
 	local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
-	printk(KERN_INFO "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
+	printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
 	       "ITC freq=%lu.%03luMHz+/-%ldppm\n", smp_processor_id(),
 	       platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
 	       itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000,
diff -Nru a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
--- a/arch/ia64/kernel/vmlinux.lds.S	2004-05-27 08:16:11 -07:00
+++ b/arch/ia64/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -135,12 +135,6 @@
 	  *(.init.setup)
 	  __setup_end = .;
 	}
-  __param : AT(ADDR(__param) - LOAD_OFFSET)
-        {
-	  __start___param = .;
-	  *(__param)
-	  __stop___param = .;
-	}
   .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET)
 	{
 	  __initcall_start = .;
diff -Nru a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
--- a/arch/ia64/lib/swiotlb.c	2004-03-22 06:34:46 -08:00
+++ b/arch/ia64/lib/swiotlb.c	2004-08-17 15:52:39 -07:00
@@ -11,6 +11,7 @@
  * 03/05/07 davidm	Switch from PCI-DMA to generic device DMA API.
  * 00/12/13 davidm	Rename to swiotlb.c and add mark_clean() to avoid
  *			unnecessary i-cache flushing.
+ * 04/07/.. ak          Better overflow handling. Assorted fixes.
  */
 
 #include <linux/cache.h>
@@ -20,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/ctype.h>
 
 #include <asm/io.h>
 #include <asm/pci.h>
@@ -46,6 +48,8 @@
  */
 #define IO_TLB_SHIFT 11
 
+int swiotlb_force;
+
 /*
  * Used to do a quick range check in swiotlb_unmap_single and swiotlb_sync_single_*, to see
  * if the memory was in fact allocated by this API.
@@ -55,8 +59,16 @@
 /*
  * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and io_tlb_end.
  * This is command line adjustable via setup_io_tlb_npages.
+ * Default to 64MB.
+ */
+static unsigned long io_tlb_nslabs = 32768;
+
+/* 
+ * When the IOMMU overflows we return a fallback buffer. This sets the size.
  */
-static unsigned long io_tlb_nslabs = 1024;
+static unsigned long io_tlb_overflow = 32*1024;
+
+void *io_tlb_overflow_buffer; 
 
 /*
  * This is a free list describing the number of free entries available from each index
@@ -78,15 +90,19 @@
 static int __init
 setup_io_tlb_npages (char *str)
 {
-	io_tlb_nslabs = simple_strtoul(str, NULL, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
-
-	/* avoid tail segment of size < IO_TLB_SEGSIZE */
-	io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
-
+	if (isdigit(*str)) { 
+		io_tlb_nslabs = simple_strtoul(str, &str, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
+		/* avoid tail segment of size < IO_TLB_SEGSIZE */
+		io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+	}
+	if (*str == ',')
+		++str;
+	if (!strcmp(str, "force"))
+		swiotlb_force = 1;
 	return 1;
 }
 __setup("swiotlb=", setup_io_tlb_npages);
-
+/* make io_tlb_overflow tunable too? */
 
 /*
  * Statically reserve bounce buffer space and initialize bounce buffer data structures for
@@ -102,7 +118,7 @@
 	 */
 	io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
 	if (!io_tlb_start)
-		BUG();
+		panic("Cannot allocate SWIOTLB buffer");
 	io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
 
 	/*
@@ -115,10 +131,22 @@
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
 	io_tlb_index = 0;
 	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
-
-	printk(KERN_INFO "Placing software IO TLB between 0x%p - 0x%p\n",
-	       (void *) io_tlb_start, (void *) io_tlb_end);
-}
+	
+	/* 
+	 * Get the overflow emergency buffer 
+	 */
+	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); 
+	printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n",
+	       virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
+}
+
+static inline int address_needs_mapping(struct device *hwdev, dma_addr_t addr)
+{ 
+	dma_addr_t mask = 0xffffffff; 
+	if (hwdev && hwdev->dma_mask) 
+		mask = *hwdev->dma_mask; 
+	return (addr & ~mask) != 0; 		
+} 
 
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
@@ -184,11 +212,8 @@
 				index = 0;
 		} while (index != wrap);
 
-		/*
-		 * XXX What is a suitable recovery mechanism here?  We cannot
-		 * sleep because we are called from with in interrupts!
-		 */
-		panic("map_single: could not allocate software IO TLB (%ld bytes)", size);
+		spin_unlock_irqrestore(&io_tlb_lock, flags);
+		return NULL;
 	}
   found:
 	spin_unlock_irqrestore(&io_tlb_lock, flags);
@@ -285,7 +310,7 @@
 
 	memset(ret, 0, size);
 	dev_addr = virt_to_phys(ret);
-	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
+	if (address_needs_mapping(hwdev,dev_addr))
 		panic("swiotlb_alloc_consistent: allocated memory is out of range for device");
 	*dma_handle = dev_addr;
 	return ret;
@@ -297,6 +322,28 @@
 	free_pages((unsigned long) vaddr, get_order(size));
 }
 
+static void swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
+{
+	/* 
+	 * Ran out of IOMMU space for this operation. This is very bad.
+	 * Unfortunately the drivers cannot handle this operation properly.
+	 * unless they check for pci_dma_mapping_error (most don't)
+	 * When the mapping is small enough return a static buffer to limit
+	 * the damage, or panic when the transfer is too big. 
+	 */ 
+	
+	printk(KERN_ERR 
+  "PCI-DMA: Out of SW-IOMMU space for %lu bytes at device %s\n",
+	       size, dev ? dev->bus_id : "?");
+
+	if (size > io_tlb_overflow && do_panic) {
+		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
+			panic("PCI-DMA: Memory would be corrupted\n");
+		if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) 
+			panic("PCI-DMA: Random memory would be DMAed\n"); 
+	} 
+} 
+
 /*
  * Map a single buffer of the indicated size for DMA in streaming mode.  The PCI address
  * to use is returned.
@@ -308,13 +355,14 @@
 swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir)
 {
 	unsigned long dev_addr = virt_to_phys(ptr);
+	void *map; 
 
 	if (dir == DMA_NONE)
 		BUG();
 	/*
 	 * Check if the PCI device can DMA to ptr... if so, just return ptr
 	 */
-	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) == 0)
+	if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force) 
 		/*
 		 * Device is bit capable of DMA'ing to the buffer... just return the PCI
 		 * address of ptr
@@ -324,12 +372,18 @@
 	/*
 	 * get a bounce buffer:
 	 */
-	dev_addr = virt_to_phys(map_single(hwdev, ptr, size, dir));
+	map = map_single(hwdev, ptr, size, dir);
+	if (!map) { 
+		swiotlb_full(hwdev, size, dir, 1);		
+		map = io_tlb_overflow_buffer; 
+	}
+
+	dev_addr = virt_to_phys(map);
 
 	/*
 	 * Ensure that the address returned is DMA'ble:
 	 */
-	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
+	if (address_needs_mapping(hwdev, dev_addr))
 		panic("map_single: bounce buffer is not DMA'ble");
 
 	return dev_addr;
@@ -437,9 +491,17 @@
 	for (i = 0; i < nelems; i++, sg++) {
 		addr = SG_ENT_VIRT_ADDRESS(sg);
 		dev_addr = virt_to_phys(addr);
-		if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
-			sg->dma_address = (dma_addr_t) map_single(hwdev, addr, sg->length, dir);
-		else
+		if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
+			sg->dma_address = (dma_addr_t) virt_to_phys(map_single(hwdev, addr, sg->length, dir));
+			if (!sg->dma_address) {
+				/* Don't panic here, we expect pci_map_sg users
+				   to do proper error handling. */
+				swiotlb_full(hwdev, sg->length, dir, 0); 
+				swiotlb_unmap_sg(hwdev, sg - i, i, dir);
+				sg[0].dma_length = 0;
+				return 0;
+			}
+		} else
 			sg->dma_address = dev_addr;
 		sg->dma_length = sg->length;
 	}
@@ -460,7 +522,7 @@
 
 	for (i = 0; i < nelems; i++, sg++)
 		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-			unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir);
+			unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir);
 		else if (dir == DMA_FROM_DEVICE)
 			mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
@@ -501,7 +563,7 @@
 int
 swiotlb_dma_mapping_error (dma_addr_t dma_addr)
 {
-	return 0;
+	return (dma_addr == virt_to_phys(io_tlb_overflow_buffer));
 }
 
 /*
diff -Nru a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
--- a/arch/ia64/mm/contig.c	2004-06-24 01:55:57 -07:00
+++ b/arch/ia64/mm/contig.c	2004-08-24 02:08:33 -07:00
@@ -267,7 +267,7 @@
 	efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
 	if (max_gap < LARGE_GAP) {
 		vmem_map = (struct page *) 0;
-		free_area_init_node(0, &contig_page_data, NULL, zones_size, 0,
+		free_area_init_node(0, &contig_page_data, zones_size, 0,
 				    zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	} else {
@@ -280,7 +280,8 @@
 		vmem_map = (struct page *) vmalloc_end;
 		efi_memmap_walk(create_mem_map_page_table, 0);
 
-		free_area_init_node(0, &contig_page_data, vmem_map, zones_size,
+		contig_page_data.node_mem_map = vmem_map;
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    0, zholes_size);
 
 		mem_map = contig_page_data.node_mem_map;
diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
--- a/arch/ia64/mm/discontig.c	2004-06-29 19:06:03 -07:00
+++ b/arch/ia64/mm/discontig.c	2004-08-26 23:30:29 -07:00
@@ -664,8 +664,8 @@
 
 		pfn_offset = mem_data[node].min_pfn;
 
-		free_area_init_node(node, NODE_DATA(node),
-				    vmem_map + pfn_offset, zones_size,
+		NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset;
+		free_area_init_node(node, NODE_DATA(node), zones_size,
 				    pfn_offset, zholes_size);
 	}
 
diff -Nru a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
--- a/arch/ia64/mm/fault.c	2004-03-25 07:23:45 -08:00
+++ b/arch/ia64/mm/fault.c	2004-08-27 00:02:34 -07:00
@@ -40,6 +40,7 @@
 	vma->vm_mm->total_vm += grow;
 	if (vma->vm_flags & VM_LOCKED)
 		vma->vm_mm->locked_vm += grow;
+	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
 	return 0;
 }
 
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	2004-08-09 09:41:08 -07:00
+++ b/arch/ia64/mm/init.c	2004-08-24 02:08:33 -07:00
@@ -429,20 +429,22 @@
 		    / sizeof(struct page));
 
 	if (map_start < map_end)
-		memmap_init_zone(map_start, (unsigned long) (map_end - map_start),
+		memmap_init_zone((unsigned long)(map_end - map_start),
 				 args->nid, args->zone, page_to_pfn(map_start));
 	return 0;
 }
 
 void
-memmap_init (struct page *start, unsigned long size, int nid,
-	     unsigned long zone, unsigned long start_pfn)
+memmap_init (unsigned long size, int nid, unsigned long zone,
+	     unsigned long start_pfn)
 {
 	if (!vmem_map)
-		memmap_init_zone(start, size, nid, zone, start_pfn);
+		memmap_init_zone(size, nid, zone, start_pfn);
 	else {
+		struct page *start;
 		struct memmap_init_callback_data args;
 
+		start = pfn_to_page(start_pfn);
 		args.start = start;
 		args.end = start + size;
 		args.nid = nid;
diff -Nru a/arch/ia64/sn/fakeprom/Makefile b/arch/ia64/sn/fakeprom/Makefile
--- a/arch/ia64/sn/fakeprom/Makefile	2003-03-18 08:17:12 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,29 +0,0 @@
-# arch/ia64/sn/fakeprom/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-#  Copyright (c) 2000-2003 Silicon Graphics, Inc.  All rights reserved.
-#
-# Medusa fake PROM support
-#
-
-EXTRA_TARGETS := fpromasm.o main.o fw-emu.o fpmem.o klgraph_init.o \
-		 fprom vmlinux.sym
-
-OBJS := $(obj)/fpromasm.o $(obj)/main.o $(obj)/fw-emu.o $(obj)/fpmem.o \
-	$(obj)/klgraph_init.o
-
-LDFLAGS_fprom = -static -T
-
-.PHONY: fprom
-
-fprom: $(obj)/fprom
-
-$(obj)/fprom: $(src)/fprom.lds $(OBJS) arch/ia64/lib/lib.a FORCE
-	$(call if_changed,ld)
-
-$(obj)/vmlinux.sym: $(src)/make_textsym System.map
-	$(src)/make_textsym vmlinux > vmlinux.sym
-	$(call cmd,cptotop)
diff -Nru a/arch/ia64/sn/fakeprom/README b/arch/ia64/sn/fakeprom/README
--- a/arch/ia64/sn/fakeprom/README	2004-01-18 22:36:01 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,93 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-This directory contains the files required to build
-the fake PROM image that is currently being used to
-boot IA64 kernels running under the SGI Medusa kernel.
-
-The FPROM currently provides the following functions:
-
-	- PAL emulation for all PAL calls we've made so far.
-	- SAL emulation for all SAL calls we've made so far.
-	- EFI emulation for all EFI calls we've made so far.
-	- builds the "ia64_bootparam" structure that is
-	  passed to the kernel from SAL. This structure 
-	  shows the cpu & memory configurations.
-	- supports medusa boottime options for changing
-	  the number of cpus present
-	- supports medusa boottime options for changing
-	  the memory configuration.
-
-
-
-At some point, this fake PROM will be replaced by the
-real PROM.
-
-
-
-
-To build a fake PROM, cd to this directory & type:
-
-	make
-
-This will (or should) build a fake PROM named "fprom".
-
-
-
-
-Use this fprom image when booting the Medusa simulator. The
-control file used to boot Medusa should include the 
-following lines:
-
-	load fprom
-	load vmlinux
-	sr pc 0x100000
-	sr g 9 <address of kernel _start function> #(currently 0xe000000000520000)
-
-NOTE: There is a script "runsim" in this directory that can be used to
-simplify setting up an environment for running under Medusa.
-
-
-
-
-The following parameters may be passed to the fake PROM to
-control the PAL/SAL/EFI parameters passed to the kernel:
-
-	GR[8] = # of cpus
-	GR[9] = address of primary entry point into the kernel
-	GR[20] = memory configuration for node 0
-	GR[21] = memory configuration for node 1
-	GR[22] = memory configuration for node 2
-	GR[23] = memory configuration for node 3
-
-
-Registers GR[20] - GR[23] contain information to specify the
-amount of memory present on nodes 0-3.
-
-  - if nothing is specified (all registers are 0), the configuration
-    defaults to 8 MB on node 0.
-
-  - a mem config entry for node N is passed in GR[20+N]
-
-  - a mem config entry consists of 8 hex digits. Each digit gives the
-    amount of physical memory available on the node starting at
-    1GB*<dn>, where dn is the digit number. The amount of memory
-    is 8MB*2**<d>. (If <d> = 0, the memory size is 0).
-
-    SN1 doesn't support dimms this small but small memory systems 
-    boot faster on Medusa.
-
-
-
-An example helps a lot. The following specifies that node 0 has
-physical memory 0 to 8MB and 1GB to 1GB+32MB, and that node 1 has
-64MB starting at address 0 of the node which is 8GB.
-
-      gr[20] = 0x21           # 0 to 8MB, 1GB to 1GB+32MB
-      gr[21] = 0x4            # 8GB to 8GB+64MB
-
diff -Nru a/arch/ia64/sn/fakeprom/fpmem.c b/arch/ia64/sn/fakeprom/fpmem.c
--- a/arch/ia64/sn/fakeprom/fpmem.c	2003-05-16 04:18:17 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,252 +0,0 @@
-/* 
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc.  All rights reserved.
- */
-
-
-
-/*
- * FPROM EFI memory descriptor build routines
- *
- * 	- Routines to build the EFI memory descriptor map
- * 	- Should also be usable by the SGI prom to convert
- * 	  klconfig to efi_memmap
- */
-
-#include <linux/config.h>
-#include <linux/efi.h>
-#include "fpmem.h"
-
-/*
- * args points to a layout in memory like this
- *
- *		32 bit		32 bit
- *
- * 		numnodes	numcpus
- *
- *		16 bit   16 bit		   32 bit
- *		nasid0	cpuconf		membankdesc0
- *		nasid1	cpuconf		membankdesc1
- *			   .
- *			   .
- *			   .
- *			   .
- *			   .
- */
-
-sn_memmap_t	*sn_memmap ;
-sn_config_t	*sn_config ;
-
-/*
- * There is a hole in the node 0 address space. Dont put it
- * in the memory map
- */
-#define NODE0_HOLE_SIZE         (20*MB)
-#define NODE0_HOLE_END          (4UL*GB)
-
-#define	MB			(1024*1024)
-#define GB			(1024*MB)
-#define KERNEL_SIZE		(4*MB)
-#define PROMRESERVED_SIZE	(1*MB)
-
-#ifdef SGI_SN2
-#define PHYS_ADDRESS(_n, _x)		(((long)_n<<38) | (long)_x | 0x3000000000UL)
-#define MD_BANK_SHFT 34
-#endif
-
-/*
- * For SN, this may not take an arg and gets the numnodes from 
- * the prom variable or by traversing klcfg or promcfg
- */
-int
-GetNumNodes(void)
-{
-	return sn_config->nodes;
-}
-
-int
-GetNumCpus(void)
-{
-	return sn_config->cpus;
-}
-
-/* For SN, get the index th nasid */
-
-int
-GetNasid(int index)
-{
-	return sn_memmap[index].nasid ;
-}
-
-node_memmap_t
-GetMemBankInfo(int index)
-{
-	return sn_memmap[index].node_memmap ;
-}
-
-int
-IsCpuPresent(int cnode, int cpu)
-{
-	return  sn_memmap[cnode].cpuconfig & (1UL<<cpu);
-}
-
-
-/*
- * Made this into an explicit case statement so that
- * we can assign specific properties to banks like bank0
- * actually disabled etc.
- */
-
-#ifdef SGI_SN2
-int
-IsBankPresent(int index, node_memmap_t nmemmap)
-{
-	switch (index) {
-		case 0:return BankPresent(nmemmap.b0size);
-		case 1:return BankPresent(nmemmap.b1size);
-		case 2:return BankPresent(nmemmap.b2size);
-		case 3:return BankPresent(nmemmap.b3size);
-		default:return -1 ;
-	}
-}
-
-int
-GetBankSize(int index, node_memmap_t nmemmap)
-{
-	/*
-	 * Add 2 because there are 4 dimms per bank.
-	 */
-        switch (index) {
-                case 0:return 2 + ((long)nmemmap.b0size + nmemmap.b0dou);
-                case 1:return 2 + ((long)nmemmap.b1size + nmemmap.b1dou);
-                case 2:return 2 + ((long)nmemmap.b2size + nmemmap.b2dou);
-                case 3:return 2 + ((long)nmemmap.b3size + nmemmap.b3dou);
-                default:return -1 ;
-        }
-}
-
-#endif
-
-void
-build_mem_desc(efi_memory_desc_t *md, int type, long paddr, long numbytes, long attr)
-{
-        md->type = type;
-        md->phys_addr = paddr;
-        md->virt_addr = 0;
-        md->num_pages = numbytes >> 12;
-        md->attribute = attr;
-}
-
-int
-build_efi_memmap(void *md, int mdsize)
-{
-	int		numnodes = GetNumNodes() ;
-	int		cnode,bank ;
-	int		nasid ;
-	node_memmap_t	membank_info ;
-	int		bsize;
-	int		count = 0 ;
-	long		paddr, hole, numbytes;
-
-
-	for (cnode=0;cnode<numnodes;cnode++) {
-		nasid = GetNasid(cnode) ;
-		membank_info = GetMemBankInfo(cnode) ;
-		for (bank=0;bank<MD_BANKS_PER_NODE;bank++) {
-			if (IsBankPresent(bank, membank_info)) {
-				bsize = GetBankSize(bank, membank_info) ;
-                                paddr = PHYS_ADDRESS(nasid, (long)bank<<MD_BANK_SHFT);
-                                numbytes = BankSizeBytes(bsize);
-#ifdef SGI_SN2
-				/* 
-				 * Ignore directory.
-				 * Shorten memory chunk by 1 page - makes a better
-				 * testcase & is more like the real PROM.
-				 */
-				numbytes = numbytes * 31 / 32;
-#endif
-				/*
-				 * Only emulate the memory prom grabs
-				 * if we have lots of memory, to allow
-				 * us to simulate smaller memory configs than
-				 * we can actually run on h/w.  Otherwise,
-				 * linux throws away a whole "granule".
-				 */
-				if (cnode == 0 && bank == 0 &&
-				    numbytes > 128*1024*1024) {
-					numbytes -= 1000;
-				}
-
-                                /*
-                                 * Check for the node 0 hole. Since banks cant
-                                 * span the hole, we only need to check if the end of
-                                 * the range is the end of the hole.
-                                 */
-                                if (paddr+numbytes == NODE0_HOLE_END)
-                                        numbytes -= NODE0_HOLE_SIZE;
-                                /*
-                                 * UGLY hack - we must skip overr the kernel and
-                                 * PROM runtime services but we dont exactly where it is.
-                                 * So lets just reserve:
-				 *	node 0
-				 *		0-1MB for PAL
-				 *		1-4MB for SAL
-				 *	node 1-N
-				 *		0-1 for SAL
-                                 */
-                                if (bank == 0) {
-					if (cnode == 0) {
-						hole = 2*1024*1024;
-						build_mem_desc(md, EFI_PAL_CODE, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
-						numbytes -= hole;
-                                        	paddr += hole;
-			        		count++ ;
-                                        	md += mdsize;
-						hole = 1*1024*1024;
-						build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, hole, EFI_MEMORY_UC);
-						numbytes -= hole;
-                                        	paddr += hole;
-			        		count++ ;
-                                        	md += mdsize;
-						hole = 1*1024*1024;
-						build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
-						numbytes -= hole;
-                                        	paddr += hole;
-			        		count++ ;
-                                        	md += mdsize;
-					} else {
-						hole = 2*1024*1024;
-                                        	build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
-						numbytes -= hole;
-                                        	paddr += hole;
-			        		count++ ;
-                                        	md += mdsize;
-						hole = 2*1024*1024;
-                                        	build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_UC);
-						numbytes -= hole;
-                                        	paddr += hole;
-			        		count++ ;
-                                        	md += mdsize;
-					}
-                                }
-                                build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, numbytes, EFI_MEMORY_WB|EFI_MEMORY_WB);
-
-			        md += mdsize ;
-			        count++ ;
-			}
-		}
-	}
-	return count ;
-}
-
-void
-build_init(unsigned long args)
-{
-	sn_config = (sn_config_t *) (args);	
-	sn_memmap = (sn_memmap_t *)(args + 8) ; /* SN equiv for this is */
-						/* init to klconfig start */
-}
diff -Nru a/arch/ia64/sn/fakeprom/fpmem.h b/arch/ia64/sn/fakeprom/fpmem.h
--- a/arch/ia64/sn/fakeprom/fpmem.h	2003-05-16 04:18:18 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,76 +0,0 @@
-/* 
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc.  All rights reserved.
- */
-
-#include <linux/config.h>
-
-/*
- * Structure of the mem config of the node as a SN MI reg
- * Medusa supports this reg config.
- *
- * BankSize nibble to bank size mapping
- *
- *      1 - 64 MB
- *      2 - 128 MB
- *      3 - 256 MB
- *      4 - 512 MB
- *      5 - 1024 MB (1GB)
- */
-
-#define MBSHIFT				20
-
-#ifdef SGI_SN2
-typedef struct node_memmap_s
-{
-        unsigned int    b0size  :3,     /* 0-2   bank 0 size */
-                        b0dou   :1,     /* 3     bank 0 is 2-sided */
-                        ena0    :1,     /* 4     bank 0 enabled */
-                        r0      :3,     /* 5-7   reserved */
-        		b1size  :3,     /* 8-10  bank 1 size */
-                        b1dou   :1,     /* 11    bank 1 is 2-sided */
-                        ena1    :1,     /* 12    bank 1 enabled */
-                        r1      :3,     /* 13-15 reserved */
-        		b2size  :3,     /* 16-18 bank 2 size */
-                        b2dou   :1,     /* 19    bank 1 is 2-sided */
-                        ena2    :1,     /* 20    bank 2 enabled */
-                        r2      :3,     /* 21-23 reserved */
-        		b3size  :3,     /* 24-26 bank 3 size */
-                        b3dou   :1,     /* 27    bank 3 is 2-sided */
-                        ena3    :1,     /* 28    bank 3 enabled */
-                        r3      :3;     /* 29-31 reserved */
-} node_memmap_t ;
-
-#define SN2_BANK_SIZE_SHIFT		(MBSHIFT+6)     /* 64 MB */
-#define BankPresent(bsize)		(bsize<6)
-#define BankSizeBytes(bsize)            (BankPresent(bsize) ? 1UL<<((bsize)+SN2_BANK_SIZE_SHIFT) : 0)
-#define MD_BANKS_PER_NODE 4
-#define MD_BANKSIZE			(1UL << 34)
-#endif
-
-typedef struct sn_memmap_s
-{
-	short		nasid ;
-	short		cpuconfig;
-	node_memmap_t 	node_memmap ;
-} sn_memmap_t ;
-
-typedef struct sn_config_s
-{
-	int		cpus;
-	int		nodes;
-	sn_memmap_t	memmap[1];		/* start of array */
-} sn_config_t;
-
-
-
-extern void build_init(unsigned long);
-extern int build_efi_memmap(void *, int);
-extern int GetNumNodes(void);
-extern int GetNumCpus(void);
-extern int IsCpuPresent(int, int);
-extern int GetNasid(int);
diff -Nru a/arch/ia64/sn/fakeprom/fprom.lds b/arch/ia64/sn/fakeprom/fprom.lds
--- a/arch/ia64/sn/fakeprom/fprom.lds	2004-01-18 22:36:01 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,103 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-OUTPUT_FORMAT("elf64-ia64-little")
-OUTPUT_ARCH(ia64)
-ENTRY(_start)
-SECTIONS
-{
-  v = 0x0000000000000000 ;	/* this symbol is here to make debugging with kdb easier... */
-
-  . = (0x000000000000000  + 0x100000) ;
-
-  _text = .;
-  .text : AT(ADDR(.text) - 0x0000000000000000 )
-    {
-	*(__ivt_section)
-	/* these are not really text pages, but the zero page needs to be in a fixed location: */
-	*(__special_page_section)
-	__start_gate_section = .;
-	*(__gate_section)
-	__stop_gate_section = .;
-	*(.text)
-    }
-
-  /* Global data */
-  _data = .;
-
-  .rodata : AT(ADDR(.rodata) - 0x0000000000000000 )
-	{ *(.rodata) *(.rodata.*) }
-  .opd : AT(ADDR(.opd) - 0x0000000000000000 )
-	{ *(.opd) }
-  .data : AT(ADDR(.data) - 0x0000000000000000 )
-	{ *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
-
-  __gp = ALIGN (8) + 0x200000;
-
-  .got : AT(ADDR(.got) - 0x0000000000000000 )
-	{ *(.got.plt) *(.got) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata : AT(ADDR(.sdata) - 0x0000000000000000 )
-	{ *(.sdata) }
-  _edata  =  .;
-  _bss = .;
-  .sbss : AT(ADDR(.sbss) - 0x0000000000000000 )
-	{ *(.sbss) *(.scommon) }
-  .bss : AT(ADDR(.bss) - 0x0000000000000000 )
-	{ *(.bss) *(COMMON) }
-  . = ALIGN(64 / 8);
-  _end = .;
-
-  /* Sections to be discarded */
-  /DISCARD/ : {
-	*(.text.exit)
-	*(.data.exit)
-	}
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  /* DWARF debug sections.
-     Symbols in the DWARF debugging sections are relative to the beginning
-     of the section so we begin them at 0.  */
-  /* DWARF 1 */
-  .debug          0 : { *(.debug) }
-  .line           0 : { *(.line) }
-  /* GNU DWARF 1 extensions */
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  /* DWARF 1.1 and DWARF 2 */
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  /* DWARF 2 */
-  .debug_info     0 : { *(.debug_info) }
-  .debug_abbrev   0 : { *(.debug_abbrev) }
-  .debug_line     0 : { *(.debug_line) }
-  .debug_frame    0 : { *(.debug_frame) }
-  .debug_str      0 : { *(.debug_str) }
-  .debug_loc      0 : { *(.debug_loc) }
-  .debug_macinfo  0 : { *(.debug_macinfo) }
-  /* SGI/MIPS DWARF 2 extensions */
-  .debug_weaknames 0 : { *(.debug_weaknames) }
-  .debug_funcnames 0 : { *(.debug_funcnames) }
-  .debug_typenames 0 : { *(.debug_typenames) }
-  .debug_varnames  0 : { *(.debug_varnames) }
-  /* These must appear regardless of  .  */
-  /* Discard them for now since Intel SoftSDV cannot handle them.
-  .comment 0 : { *(.comment) }
-  .note 0 : { *(.note) }
-  */
-  /DISCARD/ : { *(.comment) }
-  /DISCARD/ : { *(.note) }
-}
diff -Nru a/arch/ia64/sn/fakeprom/fpromasm.S b/arch/ia64/sn/fakeprom/fpromasm.S
--- a/arch/ia64/sn/fakeprom/fpromasm.S	2003-05-16 04:18:17 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,395 +0,0 @@
-/* 
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- *   (Code copied from or=ther files)
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
- */
-
-
-
-#define __ASSEMBLY__ 1
-#include <linux/config.h>
-#include <asm/processor.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/sn2/shub_mmr.h>
-
-/*
- * This file contains additional set up code that is needed to get going on
- * Medusa.  This code should disappear once real hw is available.
- *
- * On entry to this routine, the following register values are assumed:
- *
- *	gr[8]	- BSP cpu
- *	pr[9]	- kernel entry address
- *	pr[10]	- cpu number on the node
- *
- * NOTE:
- *   This FPROM may be loaded/executed at an address different from the
- *   address that it was linked at. The FPROM is linked to run on node 0
- *   at address 0x100000. If the code in loaded into another node, it
- *   must be loaded at offset 0x100000 of the node. In addition, the
- *   FPROM does the following things:
- *		- determine the base address of the node it is loaded on
- *		- add the node base to _gp.
- *		- add the node base to all addresses derived from "movl" 
- *		  instructions. (I couldnt get GPREL addressing to work)
- *		  (maybe newer versions of the tools will support this)
- *		- scan the .got section and add the node base to all
- *		  pointers in this section.
- *		- add the node base to all physical addresses in the
- *		  SAL/PAL/EFI table built by the C code. (This is done
- *		  in the C code - not here)
- *		- add the node base to the TLB entries for vmlinux
- */
-
-#define KERNEL_BASE	0xe000000000000000
-#define BOOT_PARAM_ADDR 0x40000
-
-
-/* 
- * ar.k0 gets set to IOPB_PA value, on 460gx chipset it should 
- * be 0x00000ffffc000000, but on snia we use the (inverse swizzled)
- * IOSPEC_BASE value
- */
-#ifdef SGI_SN2
-#define IOPB_PA		0xc000000fcc000000
-#endif
-
-#define RR_RID		8
-
-
-
-// ====================================================================================	
-        .text
-        .align 16
-	.global _start
-	.proc _start
-_start:
-
-// Setup psr and rse for system init
-	mov		psr.l = r0;;
-	srlz.d;;
-	invala
-	mov		ar.rsc = r0;;
-	loadrs
-	;;
-
-// Isolate node number we are running on.
-	mov		r6 = ip;;
-#ifdef SGI_SN2
-	shr		r5 = r6,38			// r5 = node number
-	dep		r6 = 0,r6,0,36			// r6 = base memory address of node
-
-#endif
-
-
-// Set & relocate gp.
-	movl		r1= __gp;;			// Add base memory address
-	or 		r1 = r1,r6			// Relocate to boot node
-
-// Lets figure out who we are & put it in the LID register.
-#ifdef SGI_SN2
-// On SN2, we (currently) pass the cpu number in r10 at boot
-	and		r25=3,r10;;
-	movl		r16=0x8000008110000400		// Allow IPIs
-	mov		r17=-1;;
-	st8		[r16]=r17
-	movl		r16=0x8000008110060580;;	// SHUB_ID
-	ld8		r27=[r16];;
-	extr.u		r27=r27,32,11;;
-	shl 		r26=r25,28;;			// Align local cpu# to lid.eid
-	shl 		r27=r27,16;;			// Align NASID to lid.id
-	or  		r26=r26,r27;;			// build the LID
-#else
-// The BR_PI_SELF_CPU_NUM register gives us a value of 0-3.
-// This identifies the cpu on the node. 
-// Merge the cpu number with the NASID to generate the LID.
-	movl		r24=0x80000a0001000020;;	// BR_PI_SELF_CPU_NUM
-	ld8 		r25=[r24]			// Fetch PI_SELF
-	movl		r27=0x80000a0001600000;;	// Fetch REVID to get local NASID
-	ld8 		r27=[r27];;
-	extr.u		r27=r27,32,8;;
-	shl 		r26=r25,16;;			// Align local cpu# to lid.eid
-	shl 		r27=r27,24;;			// Align NASID to lid.id
-	or  		r26=r26,r27;;			// build the LID
-#endif
-	mov 		cr.lid=r26			// Now put in in the LID register
-
-	movl		r2=FPSR_DEFAULT;;
-	mov 		ar.fpsr=r2
-	movl		sp = bootstacke-16;;
-	or 		sp = sp,r6			// Relocate to boot node			
-
-// Save the NASID that we are loaded on.
-	movl		r2=base_nasid;;			// Save base_nasid for C code
-	or 		r2 = r2,r6;;			// Relocate to boot node
-  	st8 		[r2]=r5				// Uncond st8 - same on all cpus
-
-// Save the kernel entry address. It is passed in r9 on one of
-// the cpus.
-	movl		r2=bsp_entry_pc
-	cmp.ne		p6,p0=r9,r0;;
-	or 		r2 = r2,r6;;			// Relocate to boot node
-(p6)  	st8 		[r2]=r9				// Uncond st8 - same on all cpus
-
-
-// The following can ONLY be done by 1 cpu. Lets set a lock - the
-// cpu that gets it does the initilization. The rest just spin waiting
-// til initilization is complete.
-	movl		r22 = initlock;;
-	or		r22 = r22,r6			// Relocate to boot node
-	mov		r23 = 1;;
-	xchg8		r23 = [r22],r23;;
-	cmp.eq 		p6,p0 = 0,r23
-(p6)	br.cond.spnt.few init
-1:	ld4		r23 = [r22];;
-	cmp.eq		p6,p0 = 1,r23
-(p6)	br.cond.sptk	1b
-	br		initx
-
-// Add base address of node memory to each pointer in the .got section.
-init:	movl		r16 = _GLOBAL_OFFSET_TABLE_;;
-	or		r16 = r16,r6;;			// Relocate to boot node
-1: 	ld8		r17 = [r16];;
-	cmp.eq		p6,p7=0,r17
-(p6)	br.cond.sptk.few.clr 2f;;
-	or		r17 = r17,r6;;			// Relocate to boot node
-	st8		[r16] = r17,8
-	br		1b
-2:
-	mov		r23 = 2;;			// All done, release the spinning cpus
-	st4		[r22] = r23
-initx:
-
-//
-//	I/O-port space base address:
-//
-	movl		r2 = IOPB_PA;;
-	mov		ar.k0 = r2
-
-
-// Now call main & pass it the current LID value.
-	alloc 		r2=ar.pfs,0,0,2,0
-	mov    		r32=r26
-	mov   		r33=r8;;
-	br.call.sptk.few rp=fmain
-	
-// Initialize Region Registers
-//
-        mov             r10 = r0
-        mov             r2 = (13<<2)
-        mov             r3 = r0;;
-1:      cmp4.gtu        p6,p7 = 7, r3
-        dep             r10 = r3, r10, 61, 3
-        dep             r2 = r3, r2, RR_RID, 4;;
-(p7)    dep             r2 = 0, r2, 0, 1;;
-(p6)    dep             r2 = -1, r2, 0, 1;;
-        mov             rr[r10] = r2
-        add             r3 = 1, r3;;
-        srlz.d;;
-        cmp4.gtu        p6,p0 = 8, r3
-(p6)    br.cond.sptk.few.clr 1b
-
-//
-// Return value indicates if we are the BSP or AP.
-// 	   1 = BSP, 0 = AP
-	mov             cr.tpr=r0;;
-	cmp.eq		p6,p0=r8,r0
-(p6)	br.cond.spnt	slave
-
-//
-// Go to kernel C startup routines
-//	Need to do a "rfi" in order set "it" and "ed" bits in the PSR.
-//	This is the only way to set them.
-
-	movl		r28=BOOT_PARAM_ADDR
-	movl		r2=bsp_entry_pc;;
-	or 		r28 = r28,r6;;			// Relocate to boot node
-	or 		r2 = r2,r6;;			// Relocate to boot node
-	ld8		r2=[r2];;
-	or		r2=r2,r6;;
-	dep		r2=0,r2,61,3;;			// convert to phys mode
-
-//
-// Turn on address translation, interrupt collection, psr.ed, protection key.
-// Interrupts (PSR.i) are still off here.
-//
-
-        movl            r3 = (  IA64_PSR_BN | \
-                                IA64_PSR_AC | \
-                                IA64_PSR_DB | \
-                                IA64_PSR_DA | \
-                                IA64_PSR_IC   \
-                             )
-        ;;
-        mov             cr.ipsr = r3
-
-//
-// Go to kernel C startup routines
-//      Need to do a "rfi" in order set "it" and "ed" bits in the PSR.
-//      This is the only way to set them.
-
-	mov		r8=r28;;
-	bsw.1		;;
-	mov		r28=r8;;
-	bsw.0		;;
-        mov             cr.iip = r2
-        srlz.d;;
-        rfi;;
-
-	.endp		_start
-
-
-
-// Slave processors come here to spin til they get an interrupt. Then they launch themselves to
-// the place ap_entry points. No initialization is necessary - the kernel makes no
-// assumptions about state on this entry.
-//	Note: should verify that the interrupt we got was really the ap_wakeup
-//	      interrupt but this should not be an issue on medusa
-slave:
-	nop.i		0x8beef				// Medusa - put cpu to sleep til interrupt occurs
-	mov		r8=cr.irr0;;			// Check for interrupt pending.
-	cmp.eq		p6,p0=r8,r0
-(p6)	br.cond.sptk	slave;;
-
-	mov		r8=cr.ivr;;			// Got one. Must read ivr to accept it
-	srlz.d;;
-	mov		cr.eoi=r0;;			// must write eoi to clear
-	movl		r8=ap_entry;;			// now jump to kernel entry
-	or 		r8 = r8,r6;;			// Relocate to boot node
-	ld8		r9=[r8],8;;
-	ld8		r1=[r8]
-	mov		b0=r9;;
-	br		b0
-
-// Here is the kernel stack used for the fake PROM
-	.bss
-	.align		16384
-bootstack:
-	.skip		16384
-bootstacke:
-initlock:
-	data4
-
-
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-// This code emulates the PAL. Only essential interfaces are emulated.
-
-
-	.text
-	.global	pal_emulator
-	.proc	pal_emulator
-pal_emulator:
-	mov	r8=-1
-
-	mov	r9=256
-	;;
-	cmp.gtu p6,p7=r9,r28		/* r28 <= 255? */
-(p6)	br.cond.sptk.few static
-	;;
-	mov	r9=512
-	;;
-	cmp.gtu p6,p7=r9,r28
-(p6)	br.cond.sptk.few stacked
-	;;
-
-static:	cmp.eq	p6,p7=6,r28		/* PAL_PTCE_INFO */
-(p7)	br.cond.sptk.few 1f
-	movl	r8=0				/* status = 0 */
-	movl	r9=0x100000000			/* tc.base */
-	movl	r10=0x0000000200000003		/* count[0], count[1] */
-	movl	r11=0x1000000000002000		/* stride[0], stride[1] */
-	;;
-
-1:	cmp.eq	p6,p7=14,r28		/* PAL_FREQ_RATIOS */
-(p7)	br.cond.sptk.few 1f
-	movl	r8=0				/* status = 0 */
-	movl	r9 =0x100000064			/* proc_ratio (1/100) */
-	movl	r10=0x100000100			/* bus_ratio<<32 (1/256) */
-	movl	r11=0x10000000a			/* itc_ratio<<32 (1/100) */
-	;;
-
-1:	cmp.eq	p6,p7=8,r28		/* PAL_VM_SUMMARY */
-(p7)	br.cond.sptk.few 1f
-	movl	r8=0
-#ifdef SGI_SN2
-	movl	r9=0x0203083001151065
-	movl	r10=0x183f
-#endif
-	movl	r11=0
-	;;
-
-1:	cmp.eq	p6,p7=19,r28		/* PAL_RSE_INFO */
-(p7)	br.cond.sptk.few 1f
-	movl	r8=0
-	movl	r9=0x60
-	movl	r10=0x0
-	movl	r11=0
-	;;
-
-1:	cmp.eq	p6,p7=15,r28		/* PAL_PERF_MON_INFO */
-(p7)	br.cond.sptk.few 1f
-	movl	r8=0
-	movl	r9=0x08122004
-	movl	r10=0x0
-	movl	r11=0
-	mov	r2=ar.lc
-	mov	r3=16;;
-	mov	ar.lc=r3
-	mov	r3=r29;;
-5:	st8	[r3]=r0,8
-	br.cloop.sptk.few 5b;;
-	mov	ar.lc=r2
-	mov	r3=r29
-	movl	r2=0x1fff;;			/* PMC regs */
-	st8	[r3]=r2
-	add	r3=32,r3
-	movl	r2=0x3ffff;;			/* PMD regs */
-	st8	[r3]=r2
-	add	r3=32,r3
-	movl	r2=0xf0;;			/* cycle regs */
-	st8	[r3]=r2
-	add	r3=32,r3
-	movl	r2=0x10;;			/* retired regs */
-	st8	[r3]=r2
-	;;
-
-1:	cmp.eq	p6,p7=19,r28		/* PAL_RSE_INFO */
-(p7)	br.cond.sptk.few 1f
-	movl	r8=0				/* status = 0 */
-	movl	r9=96				/* num phys stacked */
-	movl	r10=0				/* hints */
-	movl	r11=0
-	;;
-
-1:	cmp.eq	p6,p7=1,r28		/* PAL_CACHE_FLUSH */
-(p7)	br.cond.sptk.few 1f
-	mov	r9=ar.lc
-	movl	r8=524288				/* flush 512k million cache lines (16MB) */
-	;;
-	mov	ar.lc=r8
-	movl	r8=0xe000000000000000
-	;;
-.loop:	fc	r8
-	add	r8=32,r8
-	br.cloop.sptk.few .loop
-	sync.i
-	;;
-	srlz.i
-	;;
-	mov	ar.lc=r9
-	mov	r8=r0
-1:	br.cond.sptk.few rp
-
-stacked:
-	br.ret.sptk.few rp
-
-	.endp pal_emulator
-
diff -Nru a/arch/ia64/sn/fakeprom/fw-emu.c b/arch/ia64/sn/fakeprom/fw-emu.c
--- a/arch/ia64/sn/fakeprom/fw-emu.c	2004-07-01 22:23:48 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,775 +0,0 @@
-/*
- * PAL & SAL emulation.
- *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc.  All rights reserved.
- * 
- * This program is free software; you can redistribute it and/or modify it 
- * under the terms of version 2 of the GNU General Public License 
- * as published by the Free Software Foundation.
- * 
- * This program is distributed in the hope that it would be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * 
- * Further, this software is distributed without any warranty that it is 
- * free of the rightful claim of any third person regarding infringement 
- * or the like.  Any license provided herein, whether implied or 
- * otherwise, applies only to this software file.  Patent licenses, if 
- * any, provided herein do not apply to combinations of this program with 
- * other software, or any other product whatsoever.
- * 
- * You should have received a copy of the GNU General Public 
- * License along with this program; if not, write the Free Software 
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- * 
- * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
- * Mountain View, CA  94043, or:
- * 
- * http://www.sgi.com 
- * 
- * For further information regarding this notice, see: 
- * 
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan
- */
-#include <linux/config.h>
-#include <linux/efi.h>
-#include <linux/kernel.h>
-#include <asm/pal.h>
-#include <asm/sal.h>
-#include <asm/sn/sn_sal.h>
-#include <asm/processor.h>
-#include <asm/sn/sn_cpuid.h>
-#ifdef SGI_SN2
-#include <asm/sn/sn2/addrs.h>
-#include <asm/sn/sn2/shub_mmr.h>
-#endif
-#include <linux/acpi.h>
-#include "fpmem.h"
-
-#define RSDP_NAME               "RSDP"
-#define RSDP_SIG                "RSD PTR "  /* RSDT Pointer signature */
-#define APIC_SIG                "APIC"      /* Multiple APIC Description Table */
-#define DSDT_SIG                "DSDT"      /* Differentiated System Description Table */
-#define FADT_SIG                "FACP"      /* Fixed ACPI Description Table */
-#define FACS_SIG                "FACS"      /* Firmware ACPI Control Structure */
-#define PSDT_SIG                "PSDT"      /* Persistent System Description Table */
-#define RSDT_SIG                "RSDT"      /* Root System Description Table */
-#define XSDT_SIG                "XSDT"      /* Extended  System Description Table */
-#define SSDT_SIG                "SSDT"      /* Secondary System Description Table */
-#define SBST_SIG                "SBST"      /* Smart Battery Specification Table */
-#define SPIC_SIG                "SPIC"      /* IOSAPIC table */
-#define SRAT_SIG                "SRAT"      /* SRAT table */
-#define SLIT_SIG                "SLIT"      /* SLIT table */
-#define BOOT_SIG                "BOOT"      /* Boot table */
-#define ACPI_SRAT_REVISION 1
-#define ACPI_SLIT_REVISION 1
-
-#define OEMID			"SGI"
-#ifdef SGI_SN2
-#define PRODUCT			"SN2"
-#define PROXIMITY_DOMAIN(nasid)	(((nasid)>>1) & 255)
-#endif
-
-#define MB	(1024*1024UL)
-#define GB	(MB*1024UL)
-#define BOOT_PARAM_ADDR 0x40000
-#define MAX(i,j)		((i) > (j) ? (i) : (j))
-#define MIN(i,j)		((i) < (j) ? (i) : (j))
-#define ALIGN8(p)		(((long)(p) +7) & ~7)
-
-#define FPROM_BUG()		do {while (1);} while (0)
-#define MAX_SN_NODES		128
-#define MAX_LSAPICS		512
-#define MAX_CPUS		512
-#define MAX_CPUS_NODE		4
-#define CPUS_PER_NODE		4
-#define CPUS_PER_FSB		2
-#define CPUS_PER_FSB_MASK	(CPUS_PER_FSB-1)
-
-#define NUM_EFI_DESCS		2
-
-#define RSDP_CHECKSUM_LENGTH	20
-
-typedef union ia64_nasid_va {
-        struct {
-#if defined(SGI_SN2)
-                unsigned long off   : 36;       /* intra-region offset */
-		unsigned long attr  :  2;
-		unsigned long nasid : 11;	/* NASID */
-		unsigned long off2  : 12;	/* fill */
-                unsigned long reg   :  3;       /* region number */
-#endif
-        } f;
-        unsigned long l;
-        void *p;
-} ia64_nasid_va;
-
-typedef struct {
-	unsigned long	pc;
-	unsigned long	gp;
-} func_ptr_t;
- 
-#define IS_VIRTUAL_MODE() 	 ({struct ia64_psr psr; asm("mov %0=psr" : "=r"(psr)); psr.dt;})
-#define ADDR_OF(p)		(IS_VIRTUAL_MODE() ? ((void*)((long)(p)+PAGE_OFFSET)) : ((void*) (p)))
-
-#if defined(SGI_SN2)
-#define __fwtab_pa(n,x)		({ia64_nasid_va _v; _v.l = (long) (x); _v.f.nasid = (x) ? (n) : 0; _v.f.reg = 0; _v.f.attr = 3; _v.l;})
-#endif
-
-/*
- * The following variables are passed thru registersfrom the configuration file and
- * are set via the _start function.
- */
-long		base_nasid;
-long		num_cpus;
-long		bsp_entry_pc=0;
-long		num_nodes;
-long		app_entry_pc;
-int		bsp_lid;
-func_ptr_t	ap_entry;
-
-
-extern void pal_emulator(void);
-static efi_runtime_services_t    *efi_runtime_p;
-static char fw_mem[(  sizeof(efi_system_table_t)
-		    + sizeof(efi_runtime_services_t)
-		    + NUM_EFI_DESCS*sizeof(efi_config_table_t)
-		    + sizeof(struct ia64_sal_systab)
-		    + sizeof(struct ia64_sal_desc_entry_point)
-		    + sizeof(struct ia64_sal_desc_ap_wakeup)
-		    + sizeof(struct acpi20_table_rsdp)
-		    + sizeof(struct acpi_table_xsdt)
-		    + sizeof(struct acpi_table_slit)
-		    +   MAX_SN_NODES*MAX_SN_NODES+8
-		    + sizeof(struct acpi_table_madt)
-		    +   16*MAX_CPUS
-		    + (1+8*MAX_SN_NODES)*(sizeof(efi_memory_desc_t))
-		    + sizeof(struct acpi_table_srat)
-		    +   MAX_CPUS*sizeof(struct acpi_table_processor_affinity)
-		    +   MAX_SN_NODES*sizeof(struct acpi_table_memory_affinity)
-		    + sizeof(ia64_sal_desc_ptc_t) +
-		    + MAX_SN_NODES*sizeof(ia64_sal_ptc_domain_info_t) +
-		    + MAX_CPUS*sizeof(ia64_sal_ptc_domain_proc_entry_t) +
-		    + 1024)] __attribute__ ((aligned (8)));
-
-
-static efi_status_t
-efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
-{
-	if (tm) {
-		memset(tm, 0, sizeof(*tm));
-		tm->year = 2000;
-		tm->month = 2;
-		tm->day = 13;
-		tm->hour = 10;
-		tm->minute = 11;
-		tm->second = 12;
-	}
-
-	if (tc) {
-		tc->resolution = 10;
-		tc->accuracy = 12;
-		tc->sets_to_zero = 1;
-	}
-
-	return EFI_SUCCESS;
-}
-
-static void
-efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
-{
-	while(1);	/* Is there a pseudo-op to stop medusa */
-}
-
-static efi_status_t
-efi_success (void)
-{
-	return EFI_SUCCESS;
-}
-
-static efi_status_t
-efi_unimplemented (void)
-{
-	return EFI_UNSUPPORTED;
-}
-
-#ifdef SGI_SN2
-
-#undef cpu_physical_id
-#define cpu_physical_id(cpuid)                  ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
-
-void
-fprom_send_cpei(void) {
-        long            *p, val;
-        long            physid;
-        long            nasid, slice;
-
-        physid = cpu_physical_id(0);
-        nasid = cpu_physical_id_to_nasid(physid);
-        slice = cpu_physical_id_to_slice(physid);
-
-        p = (long*)GLOBAL_MMR_ADDR(nasid, SH_IPI_INT);
-        val =   (1UL<<SH_IPI_INT_SEND_SHFT) |
-                (physid<<SH_IPI_INT_PID_SHFT) |
-                ((long)0<<SH_IPI_INT_TYPE_SHFT) |
-                ((long)0x1e<<SH_IPI_INT_IDX_SHFT) |
-                (0x000feeUL<<SH_IPI_INT_BASE_SHFT);
-        *p = val;
-
-}
-#endif
-
-
-static struct sal_ret_values
-sal_emulator (long index, unsigned long in1, unsigned long in2,
-	      unsigned long in3, unsigned long in4, unsigned long in5,
-	      unsigned long in6, unsigned long in7)
-{
-	long r9  = 0;
-	long r10 = 0;
-	long r11 = 0;
-	long status;
-
-	/*
-	 * Don't do a "switch" here since that gives us code that
-	 * isn't self-relocatable.
-	 */
-	status = 0;
-	if (index == SAL_FREQ_BASE) {
-		switch (in1) {
-		      case SAL_FREQ_BASE_PLATFORM:
-			r9 = 500000000;
-			break;
-
-		      case SAL_FREQ_BASE_INTERVAL_TIMER:
-			/*
-			 * Is this supposed to be the cr.itc frequency
-			 * or something platform specific?  The SAL
-			 * doc ain't exactly clear on this...
-			 */
-			r9 = 700000000;
-			break;
-
-		      case SAL_FREQ_BASE_REALTIME_CLOCK:
-			r9 = 50000000;
-			break;
-
-		      default:
-			status = -1;
-			break;
-		}
-	} else if (index == SAL_SET_VECTORS) {
-		if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
-			func_ptr_t	*fp;
-			fp = ADDR_OF(&ap_entry);
-			fp->pc = in2;
-			fp->gp = in3;
-		} else if (in1 == SAL_VECTOR_OS_MCA || in1 == SAL_VECTOR_OS_INIT) {
-		} else {
-			status = -1;
-		}
-		;
-	} else if (index == SAL_GET_STATE_INFO) {
-		;
-	} else if (index == SAL_GET_STATE_INFO_SIZE) {
-		r9 = 10000;
-		;
-	} else if (index == SAL_CLEAR_STATE_INFO) {
-		;
-	} else if (index == SAL_MC_RENDEZ) {
-		;
-	} else if (index == SAL_MC_SET_PARAMS) {
-		;
-	} else if (index == SAL_CACHE_FLUSH) {
-		;
-	} else if (index == SAL_CACHE_INIT) {
-		;
-	} else if (index == SAL_UPDATE_PAL) {
-		;
-#ifdef SGI_SN2
-	} else if (index == SN_SAL_LOG_CE) {
-#ifdef ajmtestcpei
-		fprom_send_cpei();
-#else /* ajmtestcpei */
-		;
-#endif /* ajmtestcpei */
-#endif
-	} else if (index == SN_SAL_PROBE) {
-		r9 = 0UL;
-		if (in2 == 4) {
-			r9 = *(unsigned *)in1;
-			if (r9 == -1) {
-				status = 1;
-			}
-		} else if (in2 == 2) {
-			r9 = *(unsigned short *)in1;
-			if (r9 == -1) {
-				status = 1;
-			}
-		} else if (in2 == 1) {
-			r9 = *(unsigned char *)in1;
-			if (r9 == -1) {
-				status = 1;
-			}
-		} else if (in2 == 8) {
-			r9 = *(unsigned long *)in1;
-			if (r9 == -1) {
-				status = 1;
-			}
-		} else {
-			status = 2;
-		}
-	} else if (index == SN_SAL_GET_KLCONFIG_ADDR) {
-		r9 = 0x30000;
-	} else if (index == SN_SAL_CONSOLE_PUTC) {
-		status = -1;
-	} else if (index == SN_SAL_CONSOLE_GETC) {
-		status = -1;
-	} else if (index == SN_SAL_CONSOLE_POLL) {
-		status = -1;
-	} else if (index == SN_SAL_SYSCTL_IOBRICK_MODULE_GET) {
-		status = -1;
-	} else {
-		status = -1;
-	}
-
-	asm volatile ("" :: "r"(r9), "r"(r10), "r"(r11));
-	return ((struct sal_ret_values) {status, r9, r10, r11});
-}
-
-
-/*
- * This is here to work around a bug in egcs-1.1.1b that causes the
- * compiler to crash (seems like a bug in the new alias analysis code.
- */
-void *
-id (long addr)
-{
-	return (void *) addr;
-}
-
-
-/*
- * Fix the addresses in a function pointer by adding base node address
- * to pc & gp.
- */
-void
-fix_function_pointer(void *fp)
-{
-	func_ptr_t	*_fp;
-
-	_fp = fp;
-	_fp->pc = __fwtab_pa(base_nasid, _fp->pc);
-	_fp->gp = __fwtab_pa(base_nasid, _fp->gp);
-}
-
-void
-fix_virt_function_pointer(void **fptr)
-{
-        func_ptr_t      *fp;
-	long		*p;
-
-	p = (long*)fptr;
-        fp = *fptr;
-        fp->pc = fp->pc | PAGE_OFFSET;
-        fp->gp = fp->gp | PAGE_OFFSET;
-	*p |= PAGE_OFFSET;
-}
-
-
-int
-efi_set_virtual_address_map(void)
-{
-        efi_runtime_services_t            *runtime;
-
-        runtime = efi_runtime_p;
-        fix_virt_function_pointer((void**)&runtime->get_time);
-        fix_virt_function_pointer((void**)&runtime->set_time);
-        fix_virt_function_pointer((void**)&runtime->get_wakeup_time);
-        fix_virt_function_pointer((void**)&runtime->set_wakeup_time);
-        fix_virt_function_pointer((void**)&runtime->set_virtual_address_map);
-        fix_virt_function_pointer((void**)&runtime->get_variable);
-        fix_virt_function_pointer((void**)&runtime->get_next_variable);
-        fix_virt_function_pointer((void**)&runtime->set_variable);
-        fix_virt_function_pointer((void**)&runtime->get_next_high_mono_count);
-        fix_virt_function_pointer((void**)&runtime->reset_system);
-        return EFI_SUCCESS;
-}
-
-void
-acpi_table_initx(struct acpi_table_header *p, char *sig, int siglen, int revision, int oem_revision)
-{
-	memcpy(p->signature, sig, siglen);
-	memcpy(p->oem_id, OEMID, 6);
-	memcpy(p->oem_table_id, sig, 4);
-	memcpy(p->oem_table_id+4, PRODUCT, 4);
-	p->revision = revision;
-	p->oem_revision = (revision<<16) + oem_revision;
-	memcpy(p->asl_compiler_id, "FPRM", 4);
-	p->asl_compiler_revision = 1;
-}
-
-void
-acpi_checksum(struct acpi_table_header *p, int length)
-{
-	u8	*cp, *cpe, checksum;
-
-	p->checksum = 0;
-	p->length = length;
-	checksum = 0;
-	for (cp=(u8*)p, cpe=cp+p->length; cp<cpe; cp++)
-		checksum += *cp;
-	p->checksum = -checksum;
-}
-
-void
-acpi_checksum_rsdp20(struct acpi20_table_rsdp *p, int length)
-{
-	u8	*cp, *cpe, checksum;
-
-	p->checksum = 0;
-	p->ext_checksum = 0;
-	p->length = length;
-	checksum = 0;
-	for (cp=(u8*)p, cpe=cp+20; cp<cpe; cp++)
-		checksum += *cp;
-	p->checksum = -checksum;
-
-	checksum = 0;
-	for (cp=(u8*)p, cpe=cp+length; cp<cpe; cp++)
-		checksum += *cp;
-	p->ext_checksum = -checksum;
-}
-
-int
-nasid_present(int nasid)
-{
-	int	cnode;
-	for (cnode=0; cnode<num_nodes; cnode++)
-		if (GetNasid(cnode) == nasid)
-			return 1;
-	return 0;
-}
-
-void
-sys_fw_init (const char *args, int arglen, int bsp)
-{
-	/*
-	 * Use static variables to keep from overflowing the RSE stack
-	 */
-	static efi_system_table_t *efi_systab;
-	static efi_runtime_services_t *efi_runtime;
-	static efi_config_table_t *efi_tables;
-	static ia64_sal_desc_ptc_t *sal_ptc;
-	static ia64_sal_ptc_domain_info_t *sal_ptcdi;
-	static ia64_sal_ptc_domain_proc_entry_t *sal_ptclid;
-	static struct acpi20_table_rsdp *acpi20_rsdp;
-	static struct acpi_table_xsdt *acpi_xsdt;
-	static struct acpi_table_slit *acpi_slit;
-	static struct acpi_table_madt *acpi_madt;
-	static struct acpi_table_lsapic *lsapic20;
-	static struct ia64_sal_systab *sal_systab;
-	static struct acpi_table_srat *acpi_srat;
-	static struct acpi_table_processor_affinity *srat_cpu_affinity;
-	static struct acpi_table_memory_affinity *srat_memory_affinity;
-	static efi_memory_desc_t *efi_memmap, *md;
-	static unsigned long *pal_desc, *sal_desc;
-	static struct ia64_sal_desc_entry_point *sal_ed;
-	static struct ia64_boot_param *bp;
-	static struct ia64_sal_desc_ap_wakeup *sal_apwake;
-	static unsigned char checksum;
-	static char *cp, *cmd_line, *vendor;
-	static void *ptr;
-	static int mdsize, domain, last_domain ;
-	static int i, j, cnode, max_nasid, nasid, cpu, num_memmd, cpus_found;
-
-	/*
-	 * Pass the parameter base address to the build_efi_xxx routines.
-	 */
-#if defined(SGI_SN2)
-	build_init(0x3000000000UL | ((long)base_nasid<<38));
-#endif
-
-	num_nodes = GetNumNodes();
-	num_cpus = GetNumCpus();
-	for (max_nasid=0, cnode=0; cnode<num_nodes; cnode++)
-		max_nasid = MAX(max_nasid, GetNasid(cnode));
-
-
-	memset(fw_mem, 0, sizeof(fw_mem));
-
-	pal_desc = (unsigned long *) &pal_emulator;
-	sal_desc = (unsigned long *) &sal_emulator;
-	fix_function_pointer(&pal_emulator);
-	fix_function_pointer(&sal_emulator);
-
-	/* Align this to 16 bytes, probably EFI does this  */
-	mdsize = (sizeof(efi_memory_desc_t) + 15) & ~15 ;
-
-	cp = fw_mem;
-	efi_systab  = (void *) cp; cp += ALIGN8(sizeof(*efi_systab));
-	efi_runtime_p = efi_runtime = (void *) cp; cp += ALIGN8(sizeof(*efi_runtime));
-	efi_tables  = (void *) cp; cp += ALIGN8(NUM_EFI_DESCS*sizeof(*efi_tables));
-	sal_systab  = (void *) cp; cp += ALIGN8(sizeof(*sal_systab));
-	sal_ed      = (void *) cp; cp += ALIGN8(sizeof(*sal_ed));
-	sal_ptc     = (void *) cp; cp += ALIGN8(sizeof(*sal_ptc));
-	sal_apwake  = (void *) cp; cp += ALIGN8(sizeof(*sal_apwake));
-	acpi20_rsdp = (void *) cp; cp += ALIGN8(sizeof(*acpi20_rsdp));
-	acpi_xsdt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_xsdt) + 64); 
-			/* save space for more OS defined table pointers. */
-
-	acpi_slit   = (void *) cp; cp += ALIGN8(sizeof(*acpi_slit) + 8 + (max_nasid+1)*(max_nasid+1));
-	acpi_madt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_madt) + sizeof(struct acpi_table_lsapic) * (num_cpus+1));
-	acpi_srat   = (void *) cp; cp += ALIGN8(sizeof(struct acpi_table_srat));
-	cp         += sizeof(struct acpi_table_processor_affinity)*num_cpus + sizeof(struct acpi_table_memory_affinity)*num_nodes;
-	vendor 	    = (char *) cp; cp += ALIGN8(40);
-	efi_memmap  = (void *) cp; cp += ALIGN8(8*32*sizeof(*efi_memmap));
-	sal_ptcdi   = (void *) cp; cp += ALIGN8(CPUS_PER_FSB*(1+num_nodes)*sizeof(*sal_ptcdi));
-	sal_ptclid  = (void *) cp; cp += ALIGN8(((3+num_cpus)*sizeof(*sal_ptclid)+7)/8*8);
-	cmd_line    = (void *) cp;
-
-	if (args) {
-		if (arglen >= 1024)
-			arglen = 1023;
-		memcpy(cmd_line, args, arglen);
-	} else {
-		arglen = 0;
-	}
-	cmd_line[arglen] = '\0';
-	/* 
-	 * For now, just bring up bash.
-	 * If you want to execute all the startup scripts, delete the "init=..".
-	 * You can also edit this line to pass other arguments to the kernel.
-	 *    Note: disable kernel text replication.
-	 */
-	strcpy(cmd_line, "init=/bin/bash console=ttyS0");
-
-	memset(efi_systab, 0, sizeof(efi_systab));
-	efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
-	efi_systab->hdr.revision  = EFI_SYSTEM_TABLE_REVISION;
-	efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
-	efi_systab->fw_vendor = __fwtab_pa(base_nasid, vendor);
-	efi_systab->fw_revision = 1;
-	efi_systab->runtime = __fwtab_pa(base_nasid, efi_runtime);
-	efi_systab->nr_tables = 2;
-	efi_systab->tables = __fwtab_pa(base_nasid, efi_tables);
-	memcpy(vendor, "S\0i\0l\0i\0c\0o\0n\0-\0G\0r\0a\0p\0h\0i\0c\0s\0\0", 40);
-
-	efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
-	efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
-	efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
-	efi_runtime->get_time = __fwtab_pa(base_nasid, &efi_get_time);
-	efi_runtime->set_time = __fwtab_pa(base_nasid, &efi_unimplemented);
-	efi_runtime->get_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
-	efi_runtime->set_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
-	efi_runtime->set_virtual_address_map = __fwtab_pa(base_nasid, &efi_set_virtual_address_map);
-	efi_runtime->get_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
-	efi_runtime->get_next_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
-	efi_runtime->set_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
-	efi_runtime->get_next_high_mono_count = __fwtab_pa(base_nasid, &efi_unimplemented);
-	efi_runtime->reset_system = __fwtab_pa(base_nasid, &efi_reset_system);
-
-	efi_tables->guid = SAL_SYSTEM_TABLE_GUID;
-	efi_tables->table = __fwtab_pa(base_nasid, sal_systab);
-	efi_tables++;
-	efi_tables->guid = ACPI_20_TABLE_GUID;
-	efi_tables->table = __fwtab_pa(base_nasid, acpi20_rsdp);
-	efi_tables++;
-
-	fix_function_pointer(&efi_unimplemented);
-	fix_function_pointer(&efi_get_time);
-	fix_function_pointer(&efi_success);
-	fix_function_pointer(&efi_reset_system);
-	fix_function_pointer(&efi_set_virtual_address_map);
-
-
-	/* fill in the ACPI20 system table - has a pointer to the ACPI table header */
-	memcpy(acpi20_rsdp->signature, "RSD PTR ", 8);
-	acpi20_rsdp->xsdt_address = (u64)__fwtab_pa(base_nasid, acpi_xsdt);
-	acpi20_rsdp->revision = 2;
-	acpi_checksum_rsdp20(acpi20_rsdp, sizeof(struct acpi20_table_rsdp));
-
-	/* Set up the XSDT table  - contains pointers to the other ACPI tables */
-	acpi_table_initx(&acpi_xsdt->header, XSDT_SIG, 4, 1, 1);
-	acpi_xsdt->entry[0] = __fwtab_pa(base_nasid, acpi_madt);
-	acpi_xsdt->entry[1] = __fwtab_pa(base_nasid, acpi_slit);
-	acpi_xsdt->entry[2] = __fwtab_pa(base_nasid, acpi_srat);
-	acpi_checksum(&acpi_xsdt->header, sizeof(struct acpi_table_xsdt) + 16);
-
-	/* Set up the APIC table */
-	acpi_table_initx(&acpi_madt->header, APIC_SIG, 4, 1, 1);
-	lsapic20 = (struct acpi_table_lsapic*) (acpi_madt + 1);
-	for (cnode=0; cnode<num_nodes; cnode++) {
-		nasid = GetNasid(cnode);
-		for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
-			if (!IsCpuPresent(cnode, cpu))
-				continue;
-			lsapic20->header.type = ACPI_MADT_LSAPIC;
-			lsapic20->header.length = sizeof(struct acpi_table_lsapic);
-			lsapic20->acpi_id = cnode*4+cpu;
-			lsapic20->flags.enabled = 1;
-#if defined(SGI_SN2)
-			lsapic20->eid = nasid&0xffff;
-			lsapic20->id = (cpu<<4) | (nasid>>16);
-#endif
-			lsapic20 = (struct acpi_table_lsapic*) ((long)lsapic20+sizeof(struct acpi_table_lsapic));
-		}
-	}
-	acpi_checksum(&acpi_madt->header, (char*)lsapic20 - (char*)acpi_madt);
-
-	/* Set up the SRAT table */
-	acpi_table_initx(&acpi_srat->header, SRAT_SIG, 4, ACPI_SRAT_REVISION, 1);
-	ptr = acpi_srat+1;
-	for (cnode=0; cnode<num_nodes; cnode++) {
-		nasid = GetNasid(cnode);
-		srat_memory_affinity = ptr;
-		ptr = srat_memory_affinity+1;
-		srat_memory_affinity->header.type = ACPI_SRAT_MEMORY_AFFINITY;
-		srat_memory_affinity->header.length = sizeof(struct acpi_table_memory_affinity);
-		srat_memory_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid);
-		srat_memory_affinity->base_addr_lo = 0;
-		srat_memory_affinity->length_lo = 0;
-#if defined(SGI_SN2)
-		srat_memory_affinity->base_addr_hi = (nasid<<6) | (3<<4);
-		srat_memory_affinity->length_hi = (MD_BANKSIZE*MD_BANKS_PER_NODE)>>32;
-#endif
-		srat_memory_affinity->memory_type = ACPI_ADDRESS_RANGE_MEMORY;
-		srat_memory_affinity->flags.enabled = 1;
-	}
-
-	for (cnode=0; cnode<num_nodes; cnode++) {
-		nasid = GetNasid(cnode);
-		for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
-			if (!IsCpuPresent(cnode, cpu))
-				continue;
-			srat_cpu_affinity = ptr;
-			ptr = srat_cpu_affinity + 1;
-			srat_cpu_affinity->header.type = ACPI_SRAT_PROCESSOR_AFFINITY;
-			srat_cpu_affinity->header.length = sizeof(struct acpi_table_processor_affinity);
-			srat_cpu_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid);
-			srat_cpu_affinity->flags.enabled = 1;
-#if defined(SGI_SN2)
-			srat_cpu_affinity->lsapic_eid = nasid&0xffff;
-			srat_cpu_affinity->apic_id = (cpu<<4) | (nasid>>16);
-#endif
-		}
-	}
-	acpi_checksum(&acpi_srat->header, (char*)ptr - (char*)acpi_srat);
-
-
-	/* Set up the SLIT table */
-	acpi_table_initx(&acpi_slit->header, SLIT_SIG, 4, ACPI_SLIT_REVISION, 1);
-	acpi_slit->localities = PROXIMITY_DOMAIN(max_nasid)+1;
-	cp=acpi_slit->entry;
-	memset(cp, 255, acpi_slit->localities*acpi_slit->localities);
-
-	for (i=0; i<=max_nasid; i++)
-		for (j=0; j<=max_nasid; j++)
-			if (nasid_present(i) && nasid_present(j))
-				*(cp+PROXIMITY_DOMAIN(i)*acpi_slit->localities+PROXIMITY_DOMAIN(j)) = 10 + MIN(254, 5*abs(i-j));
-
-	cp = acpi_slit->entry + acpi_slit->localities*acpi_slit->localities;
-	acpi_checksum(&acpi_slit->header, cp - (char*)acpi_slit);
-
-
-	/* fill in the SAL system table: */
-	memcpy(sal_systab->signature, "SST_", 4);
-	sal_systab->size = sizeof(*sal_systab);
-	sal_systab->sal_rev_minor = 1;
-	sal_systab->sal_rev_major = 0;
-	sal_systab->entry_count = 3;
-	sal_systab->sal_b_rev_major = 0x1; /* set the SN SAL rev to */
-	sal_systab->sal_b_rev_minor = 0x0; /* 1.00 */
-
-	strcpy(sal_systab->oem_id, "SGI");
-	strcpy(sal_systab->product_id, "SN2");
-
-	/* fill in an entry point: */	
-	sal_ed->type = SAL_DESC_ENTRY_POINT;
-	sal_ed->pal_proc = __fwtab_pa(base_nasid, pal_desc[0]);
-	sal_ed->sal_proc = __fwtab_pa(base_nasid, sal_desc[0]);
-	sal_ed->gp = __fwtab_pa(base_nasid, sal_desc[1]);
-
-	/* kludge the PTC domain info */
-	sal_ptc->type = SAL_DESC_PTC;
-	sal_ptc->num_domains = 0;
-	sal_ptc->domain_info = __fwtab_pa(base_nasid, sal_ptcdi);
-	cpus_found = 0;
-	last_domain = -1;
-	sal_ptcdi--;
-	for (cnode=0; cnode<num_nodes; cnode++) {
-		nasid = GetNasid(cnode);
-		for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
-			if (IsCpuPresent(cnode, cpu)) {
-				domain = cnode*CPUS_PER_NODE + cpu/CPUS_PER_FSB;
-				if (domain != last_domain) {
-					sal_ptc->num_domains++;
-					sal_ptcdi++;
-					sal_ptcdi->proc_count = 0;
-					sal_ptcdi->proc_list = __fwtab_pa(base_nasid, sal_ptclid);
-					last_domain = domain;
-				}
-				sal_ptcdi->proc_count++;
-				sal_ptclid->id = nasid;
-				sal_ptclid->eid = cpu;
-				sal_ptclid++;
-				cpus_found++;
-			}
-		}
-	}
-
-	if (cpus_found != num_cpus)
-		FPROM_BUG();
-
-	/* Make the AP WAKEUP entry */
-	sal_apwake->type = SAL_DESC_AP_WAKEUP;
-	sal_apwake->mechanism = IA64_SAL_AP_EXTERNAL_INT;
-	sal_apwake->vector = 18;
-
-	for (checksum=0, cp=(char*)sal_systab; cp < (char *)efi_memmap; ++cp)
-		checksum += *cp;
-	sal_systab->checksum = -checksum;
-
-	/* If the checksum is correct, the kernel tries to use the
-	 * table. We dont build enough table & the kernel aborts.
-	 * Note that the PROM hasd thhhe same problem!!
-	 */
-
-	md = &efi_memmap[0];
-	num_memmd = build_efi_memmap((void *)md, mdsize) ;
-
-	bp = (struct ia64_boot_param*) __fwtab_pa(base_nasid, BOOT_PARAM_ADDR);
-	bp->efi_systab = __fwtab_pa(base_nasid, &fw_mem);
-	bp->efi_memmap = __fwtab_pa(base_nasid, efi_memmap);
-	bp->efi_memmap_size = num_memmd*mdsize;
-	bp->efi_memdesc_size = mdsize;
-	bp->efi_memdesc_version = 0x101;
-	bp->command_line = __fwtab_pa(base_nasid, cmd_line);
-	bp->console_info.num_cols = 80;
-	bp->console_info.num_rows = 25;
-	bp->console_info.orig_x = 0;
-	bp->console_info.orig_y = 24;
-	bp->fpswa = 0;
-
-	/*
-	 * Now pick the BSP & store it LID value in
-	 * a global variable. Note if BSP is greater than last cpu,
-	 * pick the last cpu.
-	 */
-	for (cnode=0; cnode<num_nodes; cnode++) {
-		for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
-			if (!IsCpuPresent(cnode, cpu))
-				continue;
-#ifdef SGI_SN2
-			bsp_lid = (GetNasid(cnode)<<16) | (cpu<<28);
-#endif
-			if (bsp-- > 0)
-				continue;
-			return;
-		}
-	}
-}
diff -Nru a/arch/ia64/sn/fakeprom/klgraph_init.c b/arch/ia64/sn/fakeprom/klgraph_init.c
--- a/arch/ia64/sn/fakeprom/klgraph_init.c	2003-05-16 04:18:17 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,205 +0,0 @@
-/* $Id: klgraph_init.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-
-/*
- * This is a temporary file that statically initializes the expected 
- * initial klgraph information that is normally provided by prom.
- */
-
-#include <linux/types.h>
-#include <linux/config.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <asm/sn/sgi.h>
-#include <asm/sn/io.h>
-#include <asm/sn/driver.h>
-#include <asm/sn/iograph.h>
-#include <asm/param.h>
-#include <asm/sn/pio.h>
-#include <asm/sn/xtalk/xwidget.h>
-#include <asm/sn/sn_private.h>
-#include <asm/sn/addrs.h>
-#include <asm/sn/invent.h>
-#include <asm/sn/hcl.h>
-#include <asm/sn/hcl_util.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/xtalk/xtalkaddrs.h>
-#include <asm/sn/klconfig.h>
-
-#define SYNERGY_WIDGET          ((char *)0xc0000e0000000000)
-#define SYNERGY_SWIZZLE         ((char *)0xc0000e0000000400)
-#define HUBREG                  ((char *)0xc0000a0001e00000)
-#define WIDGET0                 ((char *)0xc0000a0000000000)
-#define WIDGET4                 ((char *)0xc0000a0000000004)
-
-#define SYNERGY_WIDGET          ((char *)0xc0000e0000000000)
-#define SYNERGY_SWIZZLE         ((char *)0xc0000e0000000400)
-#define HUBREG                  ((char *)0xc0000a0001e00000)
-#define WIDGET0                 ((char *)0xc0000a0000000000)
-
-#define convert(a,b,c) temp = (u64 *)a; *temp = b; temp++; *temp = c
-void
-klgraph_init(void)
-{
-
-	u64 *temp;
-	/*
-	 * Initialize some hub/xbow registers that allows access to 
-	 * Xbridge etc.  These are normally done in PROM.
-	 */
-
-        /* Write IOERR clear to clear the CRAZY bit in the status */
-        *(volatile uint64_t *)0xc000000801c001f8 = (uint64_t)0xffffffff;
-
-        /* set widget control register...setting bedrock widget id to a */
-        *(volatile uint64_t *)0xc000000801c00020 = (uint64_t)0x801a;
-
-        /* set io outbound widget access...allow all */
-        *(volatile uint64_t *)0xc000000801c00110 = (uint64_t)0xff01;
-
-        /* set io inbound widget access...allow all */
-        *(volatile uint64_t *)0xc000000801c00118 = (uint64_t)0xff01;
-
-        /* set io crb timeout to max */
-        *(volatile uint64_t *)0xc000000801c003c0 = (uint64_t)0xffffff;
-        *(volatile uint64_t *)0xc000000801c003c0 = (uint64_t)0xffffff;
-
-        /* set local block io permission...allow all */
-// [LB]        *(volatile uint64_t *)0xc000000801e04010 = (uint64_t)0xfffffffffffffff;
-
-        /* clear any errors */
-        /* clear_ii_error(); medusa should have cleared these */
-
-        /* set default read response buffers in bridge */
-// [PI]       *(volatile u32 *)0xc00000080f000280L = 0xba98;
-// [PI]       *(volatile u32 *)0xc00000080f000288L = 0xba98;
-
-        /*
-         * klconfig entries initialization - mankato
-         */
-        convert(0xe000003000030000, 0x00000000beedbabe, 0x0000004800000000);
-        convert(0xe000003000030010, 0x0003007000000018, 0x800002000f820178);
-        convert(0xe000003000030020, 0x80000a000f024000, 0x800002000f800000);
-        convert(0xe000003000030030, 0x0300fafa00012580, 0x00000000040f0000);
-        convert(0xe000003000030040, 0x0000000000000000, 0x0003097000030070);
-        convert(0xe000003000030050, 0x00030970000303b0, 0x0003181000033f70);
-        convert(0xe000003000030060, 0x0003d51000037570, 0x0000000000038330);
-        convert(0xe000003000030070, 0x0203110100030140, 0x0001000000000101);
-        convert(0xe000003000030080, 0x0900000000000000, 0x000000004e465e67);
-        convert(0xe000003000030090, 0x0003097000000000, 0x00030b1000030a40);
-        convert(0xe0000030000300a0, 0x00030cb000030be0, 0x000315a0000314d0);
-        convert(0xe0000030000300b0, 0x0003174000031670, 0x0000000000000000);
-        convert(0xe000003000030100, 0x000000000000001a, 0x3350490000000000);
-        convert(0xe000003000030110, 0x0000000000000037, 0x0000000000000000);
-        convert(0xe000003000030140, 0x0002420100030210, 0x0001000000000101);
-        convert(0xe000003000030150, 0x0100000000000000, 0xffffffffffffffff);
-        convert(0xe000003000030160, 0x00030d8000000000, 0x0000000000030e50);
-        convert(0xe0000030000301c0, 0x0000000000000000, 0x0000000000030070);
-        convert(0xe0000030000301d0, 0x0000000000000025, 0x424f490000000000);
-        convert(0xe0000030000301e0, 0x000000004b434952, 0x0000000000000000);
-        convert(0xe000003000030210, 0x00027101000302e0, 0x00010000000e4101);
-        convert(0xe000003000030220, 0x0200000000000000, 0xffffffffffffffff);
-        convert(0xe000003000030230, 0x00030f2000000000, 0x0000000000030ff0);
-        convert(0xe000003000030290, 0x0000000000000000, 0x0000000000030140);
-        convert(0xe0000030000302a0, 0x0000000000000026, 0x7262490000000000);
-        convert(0xe0000030000302b0, 0x00000000006b6369, 0x0000000000000000);
-        convert(0xe0000030000302e0, 0x0002710100000000, 0x00010000000f3101);
-        convert(0xe0000030000302f0, 0x0500000000000000, 0xffffffffffffffff);
-        convert(0xe000003000030300, 0x000310c000000000, 0x0003126000031190);
-        convert(0xe000003000030310, 0x0003140000031330, 0x0000000000000000);
-        convert(0xe000003000030360, 0x0000000000000000, 0x0000000000030140);
-        convert(0xe000003000030370, 0x0000000000000029, 0x7262490000000000);
-        convert(0xe000003000030380, 0x00000000006b6369, 0x0000000000000000);
-        convert(0xe000003000030970, 0x0000000002010102, 0x0000000000000000);
-        convert(0xe000003000030980, 0x000000004e465e67, 0xffffffff00000000);
-        /* convert(0x00000000000309a0, 0x0000000000037570, 0x0000000100000000); */
-        convert(0xe0000030000309a0, 0x0000000000037570, 0xffffffff00000000);
-        convert(0xe0000030000309b0, 0x0000000000030070, 0x0000000000000000);
-        convert(0xe0000030000309c0, 0x000000000003f420, 0x0000000000000000);
-        convert(0xe000003000030a40, 0x0000000002010125, 0x0000000000000000);
-        convert(0xe000003000030a50, 0xffffffffffffffff, 0xffffffff00000000);
-        convert(0xe000003000030a70, 0x0000000000037b78, 0x0000000000000000);
-        convert(0xe000003000030b10, 0x0000000002010125, 0x0000000000000000);
-        convert(0xe000003000030b20, 0xffffffffffffffff, 0xffffffff00000000);
-        convert(0xe000003000030b40, 0x0000000000037d30, 0x0000000000000001);
-        convert(0xe000003000030be0, 0x00000000ff010203, 0x0000000000000000);
-        convert(0xe000003000030bf0, 0xffffffffffffffff, 0xffffffff000000ff);
-        convert(0xe000003000030c10, 0x0000000000037ee8, 0x0100010000000200);
-        convert(0xe000003000030cb0, 0x00000000ff310111, 0x0000000000000000);
-        convert(0xe000003000030cc0, 0xffffffffffffffff, 0x0000000000000000);
-        convert(0xe000003000030d80, 0x0000000002010104, 0x0000000000000000);
-        convert(0xe000003000030d90, 0xffffffffffffffff, 0x00000000000000ff);
-        convert(0xe000003000030db0, 0x0000000000037f18, 0x0000000000000000);
-        convert(0xe000003000030dc0, 0x0000000000000000, 0x0003007000060000);
-        convert(0xe000003000030de0, 0x0000000000000000, 0x0003021000050000);
-        convert(0xe000003000030df0, 0x000302e000050000, 0x0000000000000000);
-        convert(0xe000003000030e30, 0x0000000000000000, 0x000000000000000a);
-        convert(0xe000003000030e50, 0x00000000ff00011a, 0x0000000000000000);
-        convert(0xe000003000030e60, 0xffffffffffffffff, 0x0000000000000000);
-        convert(0xe000003000030e80, 0x0000000000037fe0, 0x9e6e9e9e9e9e9e9e);
-        convert(0xe000003000030e90, 0x000000000000bc6e, 0x0000000000000000);
-        convert(0xe000003000030f20, 0x0000000002010205, 0x00000000d0020000);
-        convert(0xe000003000030f30, 0xffffffffffffffff, 0x0000000e0000000e);
-        convert(0xe000003000030f40, 0x000000000000000e, 0x0000000000000000);
-        convert(0xe000003000030f50, 0x0000000000038010, 0x00000000000007ff);
-        convert(0xe000003000030f70, 0x0000000000000000, 0x0000000022001077);
-        convert(0xe000003000030fa0, 0x0000000000000000, 0x000000000003f4a8);
-        convert(0xe000003000030ff0, 0x0000000000310120, 0x0000000000000000);
-        convert(0xe000003000031000, 0xffffffffffffffff, 0xffffffff00000002);
-        convert(0xe000003000031010, 0x000000000000000e, 0x0000000000000000);
-        convert(0xe000003000031020, 0x0000000000038088, 0x0000000000000000);
-        convert(0xe0000030000310c0, 0x0000000002010205, 0x00000000d0020000);
-        convert(0xe0000030000310d0, 0xffffffffffffffff, 0x0000000f0000000f);
-        convert(0xe0000030000310e0, 0x000000000000000f, 0x0000000000000000);
-        convert(0xe0000030000310f0, 0x00000000000380b8, 0x00000000000007ff);
-        convert(0xe000003000031120, 0x0000000022001077, 0x00000000000310a9);
-        convert(0xe000003000031130, 0x00000000580211c1, 0x000000008009104c);
-        convert(0xe000003000031140, 0x0000000000000000, 0x000000000003f4c0);
-        convert(0xe000003000031190, 0x0000000000310120, 0x0000000000000000);
-        convert(0xe0000030000311a0, 0xffffffffffffffff, 0xffffffff00000003);
-        convert(0xe0000030000311b0, 0x000000000000000f, 0x0000000000000000);
-        convert(0xe0000030000311c0, 0x0000000000038130, 0x0000000000000000);
-        convert(0xe000003000031260, 0x0000000000110106, 0x0000000000000000);
-        convert(0xe000003000031270, 0xffffffffffffffff, 0xffffffff00000004);
-        convert(0xe000003000031270, 0xffffffffffffffff, 0xffffffff00000004);
-        convert(0xe000003000031280, 0x000000000000000f, 0x0000000000000000);
-        convert(0xe0000030000312a0, 0x00000000ff110013, 0x0000000000000000);
-        convert(0xe0000030000312b0, 0xffffffffffffffff, 0xffffffff00000000);
-        convert(0xe0000030000312c0, 0x000000000000000f, 0x0000000000000000);
-        convert(0xe0000030000312e0, 0x0000000000110012, 0x0000000000000000);
-        convert(0xe0000030000312f0, 0xffffffffffffffff, 0xffffffff00000000);
-        convert(0xe000003000031300, 0x000000000000000f, 0x0000000000000000);
-        convert(0xe000003000031310, 0x0000000000038160, 0x0000000000000000);
-        convert(0xe000003000031330, 0x00000000ff310122, 0x0000000000000000);
-        convert(0xe000003000031340, 0xffffffffffffffff, 0xffffffff00000005);
-        convert(0xe000003000031350, 0x000000000000000f, 0x0000000000000000);
-        convert(0xe000003000031360, 0x0000000000038190, 0x0000000000000000);
-        convert(0xe000003000031400, 0x0000000000310121, 0x0000000000000000);
-        convert(0xe000003000031400, 0x0000000000310121, 0x0000000000000000);
-        convert(0xe000003000031410, 0xffffffffffffffff, 0xffffffff00000006);
-        convert(0xe000003000031420, 0x000000000000000f, 0x0000000000000000);
-        convert(0xe000003000031430, 0x00000000000381c0, 0x0000000000000000);
-        convert(0xe0000030000314d0, 0x00000000ff010201, 0x0000000000000000);
-        convert(0xe0000030000314e0, 0xffffffffffffffff, 0xffffffff00000000);
-        convert(0xe000003000031500, 0x00000000000381f0, 0x000030430000ffff);
-        convert(0xe000003000031510, 0x000000000000ffff, 0x0000000000000000);
-        convert(0xe0000030000315a0, 0x00000020ff000201, 0x0000000000000000);
-        convert(0xe0000030000315b0, 0xffffffffffffffff, 0xffffffff00000001);
-        convert(0xe0000030000315d0, 0x0000000000038240, 0x00003f3f0000ffff);
-        convert(0xe0000030000315e0, 0x000000000000ffff, 0x0000000000000000);
-        convert(0xe000003000031670, 0x00000000ff010201, 0x0000000000000000);
-        convert(0xe000003000031680, 0xffffffffffffffff, 0x0000000100000002);
-        convert(0xe0000030000316a0, 0x0000000000038290, 0x000030430000ffff);
-        convert(0xe0000030000316b0, 0x000000000000ffff, 0x0000000000000000);
-        convert(0xe000003000031740, 0x00000020ff000201, 0x0000000000000000);
-        convert(0xe000003000031750, 0xffffffffffffffff, 0x0000000500000003);
-        convert(0xe000003000031770, 0x00000000000382e0, 0x00003f3f0000ffff);
-        convert(0xe000003000031780, 0x000000000000ffff, 0x0000000000000000);
-}
diff -Nru a/arch/ia64/sn/fakeprom/main.c b/arch/ia64/sn/fakeprom/main.c
--- a/arch/ia64/sn/fakeprom/main.c	2003-05-16 04:18:18 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,109 +0,0 @@
-/* 
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc.  All rights reserved.
- */
-
-
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <asm/bitops.h>
-
-extern void klgraph_init(void);
-void bedrock_init(int);
-void synergy_init(int, int);
-void sys_fw_init (const char *args, int arglen, int bsp);
-
-volatile int	bootmaster=0;		/* Used to pick bootmaster */
-volatile int	nasidmaster[128]={0};	/* Used to pick node/synergy masters */
-int		init_done=0;
-extern int	bsp_lid;
-
-#define get_bit(b,p)	(((*p)>>(b))&1)
-
-int
-fmain(int lid, int bsp) {
-	int	syn, nasid, cpu;
-
-	/*
-	 * First lets figure out who we are. This is done from the
-	 * LID passed to us.
-	 */
-	nasid = (lid>>16)&0xfff;
-	cpu = (lid>>28)&3;
-	syn = 0;
-	
-	/*
-	 * Now pick a nasid master to initialize Bedrock registers.
-	 */
-	if (test_and_set_bit(8, &nasidmaster[nasid]) == 0) {
-		bedrock_init(nasid);
-		test_and_set_bit(9, &nasidmaster[nasid]);
-	} else
-		while (get_bit(9, &nasidmaster[nasid]) == 0);
-	
-
-	/*
-	 * Now pick a BSP & finish init.
-	 */
-	if (test_and_set_bit(0, &bootmaster) == 0) {
-		sys_fw_init(0, 0, bsp);
-		test_and_set_bit(1, &bootmaster);
-	} else
-		while (get_bit(1, &bootmaster) == 0);
-
-	return (lid == bsp_lid);
-}
-
-
-void
-bedrock_init(int nasid)
-{
-	nasid = nasid;		/* to quiet gcc */
-#if 0
-	/*
-	 * Undef if you need fprom to generate a 1 node klgraph
-	 * information .. only works for 1 node for nasid 0.
-	 */
-	klgraph_init();
-#endif
-}
-
-
-void
-synergy_init(int nasid, int syn)
-{
-	long	*base;
-	long	off;
-
-	/*
-	 * Enable all FSB flashed interrupts.
-	 * I'd really like defines for this......
-	 */
-	base = (long*)0x80000e0000000000LL;		/* base of synergy regs */
-	for (off = 0x2a0; off < 0x2e0; off+=8)		/* offset for VEC_MASK_{0-3}_A/B */
-		*(base+off/8) = -1LL;
-
-	/*
-	 * Set the NASID in the FSB_CONFIG register.
-	 */
-	base = (long*)0x80000e0000000450LL;
-	*base = (long)((nasid<<16)|(syn<<9));
-}
-
-
-/* Why isnt there a bcopy/memcpy in lib64.a */
-
-void* 
-memcpy(void * dest, const void *src, size_t count)
-{
-	char *s, *se, *d;
-
-	for(d=dest, s=(char*)src, se=s+count; s<se; s++, d++)
-		*d = *s;
-	return dest;
-}
diff -Nru a/arch/ia64/sn/fakeprom/make_textsym b/arch/ia64/sn/fakeprom/make_textsym
--- a/arch/ia64/sn/fakeprom/make_textsym	2003-05-16 04:18:17 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,174 +0,0 @@
-#!/bin/sh
-#
-# Build a textsym file for use in the Arium ITP probe.
-#
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (c) 2001-2003 Silicon Graphics, Inc.  All rights reserved.
-#
-
-help() {
-cat <<END
-Build a WinDD "symtxt" file for use with the Arium ECM-30 probe.
-
-	Usage: $0 [<vmlinux file> [<output file>]]
-		If no input file is specified, it defaults to vmlinux.
-		If no output file name is specified, it defaults to "textsym".
-END
-exit 1
-}
-
-err () {
-	echo "ERROR - $*" >&2
-	exit 1
-}
-
-
-OPTS="H"
-while getopts "$OPTS" c ; do
-	case $c in
-		H)  help;;
-		\?) help;;
-	esac
-
-done
-shift `expr $OPTIND - 1`
-
-#OBJDUMP=/usr/bin/ia64-linux-objdump
-LINUX=${1:-vmlinux}
-TEXTSYM=${2:-${LINUX}.sym}
-TMPSYM=${2:-${LINUX}.sym.tmp}
-trap "/bin/rm -f $TMPSYM" 0
-
-[ -f $VMLINUX ] || help
-
-$OBJDUMP -t $LINUX | egrep -v '__ks' | sort > $TMPSYM
-SN1=`egrep "dig_setup|Synergy_da_indr" $TMPSYM|wc -l`
-
-# Dataprefix and textprefix correspond to the VGLOBAL_BASE and VPERNODE_BASE.
-# Eventually, these values should be:
-#	dataprefix	ffffffff
-#	textprefix	fffffffe
-# but right now they're still changing, so make them dynamic.
-dataprefix=`awk ' / \.data	/ { print substr($1, 0, 8) ; exit ; }' $TMPSYM`
-textprefix=`awk ' / \.text	/ { print substr($1, 0, 8) ; exit ; }' $TMPSYM`
-
-# pipe everything thru sort
-echo "TEXTSYM V1.0"
-(cat <<END 
-GLOBAL | ${textprefix}00000000 | CODE | VEC_VHPT_Translation_0000
-GLOBAL | ${textprefix}00000400 | CODE | VEC_ITLB_0400
-GLOBAL | ${textprefix}00000800 | CODE | VEC_DTLB_0800
-GLOBAL | ${textprefix}00000c00 | CODE | VEC_Alt_ITLB_0c00
-GLOBAL | ${textprefix}00001000 | CODE | VEC_Alt_DTLB_1000
-GLOBAL | ${textprefix}00001400 | CODE | VEC_Data_nested_TLB_1400
-GLOBAL | ${textprefix}00001800 | CODE | VEC_Instruction_Key_Miss_1800
-GLOBAL | ${textprefix}00001c00 | CODE | VEC_Data_Key_Miss_1c00
-GLOBAL | ${textprefix}00002000 | CODE | VEC_Dirty-bit_2000
-GLOBAL | ${textprefix}00002400 | CODE | VEC_Instruction_Access-bit_2400
-GLOBAL | ${textprefix}00002800 | CODE | VEC_Data_Access-bit_2800
-GLOBAL | ${textprefix}00002c00 | CODE | VEC_Break_instruction_2c00
-GLOBAL | ${textprefix}00003000 | CODE | VEC_External_Interrupt_3000
-GLOBAL | ${textprefix}00003400 | CODE | VEC_Reserved_3400
-GLOBAL | ${textprefix}00003800 | CODE | VEC_Reserved_3800
-GLOBAL | ${textprefix}00003c00 | CODE | VEC_Reserved_3c00
-GLOBAL | ${textprefix}00004000 | CODE | VEC_Reserved_4000
-GLOBAL | ${textprefix}00004400 | CODE | VEC_Reserved_4400
-GLOBAL | ${textprefix}00004800 | CODE | VEC_Reserved_4800
-GLOBAL | ${textprefix}00004c00 | CODE | VEC_Reserved_4c00
-GLOBAL | ${textprefix}00005000 | CODE | VEC_Page_Not_Present_5000
-GLOBAL | ${textprefix}00005100 | CODE | VEC_Key_Permission_5100
-GLOBAL | ${textprefix}00005200 | CODE | VEC_Instruction_Access_Rights_5200
-GLOBAL | ${textprefix}00005300 | CODE | VEC_Data_Access_Rights_5300
-GLOBAL | ${textprefix}00005400 | CODE | VEC_General_Exception_5400
-GLOBAL | ${textprefix}00005500 | CODE | VEC_Disabled_FP-Register_5500
-GLOBAL | ${textprefix}00005600 | CODE | VEC_Nat_Consumption_5600
-GLOBAL | ${textprefix}00005700 | CODE | VEC_Speculation_5700
-GLOBAL | ${textprefix}00005800 | CODE | VEC_Reserved_5800
-GLOBAL | ${textprefix}00005900 | CODE | VEC_Debug_5900
-GLOBAL | ${textprefix}00005a00 | CODE | VEC_Unaligned_Reference_5a00
-GLOBAL | ${textprefix}00005b00 | CODE | VEC_Unsupported_Data_Reference_5b00
-GLOBAL | ${textprefix}00005c00 | CODE | VEC_Floating-Point_Fault_5c00
-GLOBAL | ${textprefix}00005d00 | CODE | VEC_Floating_Point_Trap_5d00
-GLOBAL | ${textprefix}00005e00 | CODE | VEC_Lower_Privilege_Tranfer_Trap_5e00
-GLOBAL | ${textprefix}00005f00 | CODE | VEC_Taken_Branch_Trap_5f00
-GLOBAL | ${textprefix}00006000 | CODE | VEC_Single_Step_Trap_6000
-GLOBAL | ${textprefix}00006100 | CODE | VEC_Reserved_6100
-GLOBAL | ${textprefix}00006200 | CODE | VEC_Reserved_6200
-GLOBAL | ${textprefix}00006300 | CODE | VEC_Reserved_6300
-GLOBAL | ${textprefix}00006400 | CODE | VEC_Reserved_6400
-GLOBAL | ${textprefix}00006500 | CODE | VEC_Reserved_6500
-GLOBAL | ${textprefix}00006600 | CODE | VEC_Reserved_6600
-GLOBAL | ${textprefix}00006700 | CODE | VEC_Reserved_6700
-GLOBAL | ${textprefix}00006800 | CODE | VEC_Reserved_6800
-GLOBAL | ${textprefix}00006900 | CODE | VEC_IA-32_Exeception_6900
-GLOBAL | ${textprefix}00006a00 | CODE | VEC_IA-32_Intercept_6a00
-GLOBAL | ${textprefix}00006b00 | CODE | VEC_IA-32_Interrupt_6b00
-GLOBAL | ${textprefix}00006c00 | CODE | VEC_Reserved_6c00
-GLOBAL | ${textprefix}00006d00 | CODE | VEC_Reserved_6d00
-GLOBAL | ${textprefix}00006e00 | CODE | VEC_Reserved_6e00
-GLOBAL | ${textprefix}00006f00 | CODE | VEC_Reserved_6f00
-GLOBAL | ${textprefix}00007000 | CODE | VEC_Reserved_7000
-GLOBAL | ${textprefix}00007100 | CODE | VEC_Reserved_7100
-GLOBAL | ${textprefix}00007200 | CODE | VEC_Reserved_7200
-GLOBAL | ${textprefix}00007300 | CODE | VEC_Reserved_7300
-GLOBAL | ${textprefix}00007400 | CODE | VEC_Reserved_7400
-GLOBAL | ${textprefix}00007500 | CODE | VEC_Reserved_7500
-GLOBAL | ${textprefix}00007600 | CODE | VEC_Reserved_7600
-GLOBAL | ${textprefix}00007700 | CODE | VEC_Reserved_7700
-GLOBAL | ${textprefix}00007800 | CODE | VEC_Reserved_7800
-GLOBAL | ${textprefix}00007900 | CODE | VEC_Reserved_7900
-GLOBAL | ${textprefix}00007a00 | CODE | VEC_Reserved_7a00
-GLOBAL | ${textprefix}00007b00 | CODE | VEC_Reserved_7b00
-GLOBAL | ${textprefix}00007c00 | CODE | VEC_Reserved_7c00
-GLOBAL | ${textprefix}00007d00 | CODE | VEC_Reserved_7d00
-GLOBAL | ${textprefix}00007e00 | CODE | VEC_Reserved_7e00
-GLOBAL | ${textprefix}00007f00 | CODE | VEC_Reserved_7f00
-END
-
-
-awk '
-/ _start$/ {start=1}
-/ start_ap$/ {start=1}
-/__start_gate_section/ {start=1}
-/^'${dataprefix}\|${textprefix}'/ {
-	if ($4 == ".kdb")
-		next
-	if (start && substr($NF,1,1) != "0") {
-		type = substr($0,26,5)
-		if (type == ".text")
-			printf "GLOBAL | %s | CODE | %s\n", $1, $NF
-		else {
-			n = 0
-			s = $(NF-1)
-			while (length(s) > 0) {
-				n = n*16 + (index("0123456789abcdef", substr(s,1,1)) - 1)
-				s = substr(s,2)
-			}
-			printf "GLOBAL | %s | DATA | %s | %d\n", $1, $NF, n
-		}
-	}
-	if($NF == "_end") 
-		exit
-
-}
-' $TMPSYM ) | egrep -v " __device| __vendor" | awk -v sn1="$SN1" '
-/GLOBAL/ {
-	print $0
-	if (sn1 != 0) {
-		/* 32 bits of sn1 physical addrs, */
-		print substr($0,1,9) "04" substr($0,20,16) "Phy_" substr($0,36)
-	} else {
-		/* 38 bits of sn2 physical addrs, need addr space bits */
-		print substr($0,1,9) "3004" substr($0,20,16) "Phy_" substr($0,36)
-	}
-
-} ' | sort -k3
-
-N=`wc -l $TEXTSYM|awk '{print $1}'`
-echo "Generated TEXTSYM file" >&2
-echo "  $LINUX --> $TEXTSYM" >&2
-echo "  Found $N symbols" >&2
diff -Nru a/arch/ia64/sn/fakeprom/runsim b/arch/ia64/sn/fakeprom/runsim
--- a/arch/ia64/sn/fakeprom/runsim	2002-03-08 18:11:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,387 +0,0 @@
-#!/bin/sh
-
-# Script for running PROMs and LINUX kernwls on medusa. 
-# Type "sim -H" for instructions.
-
-MEDUSA=${MEDUSA:-/home/rickc/official_medusa/medusa}
-
-# ------------------ err -----------------------
-err() {
-	echo "ERROR - $1"
-	exit 1
-}
-
-# ----------------  help ----------------------
-help() {
-cat <<END
-Script for running a PROM or LINUX kernel under medusa.
-This script creates a control file, creates links to the appropriate
-linux/prom files, and/or calls medusa to make simulation runs.
-
-Usage:  
-   Initial setup:
-   	sim [-c <config_file>] <-p> | <-k>  [<work_dir>]
-		-p	Create PROM control file & links
-		-k	Create LINUX control file & links
-		-c<cf>	Control file name				[Default: cf]
-		<work_dir> Path to directory that contains the linux or PROM files.
-		    The directory can be any of the following:
-		       (linux simulations)
-		       		worktree
-				worktree/linux
-				any directory with vmlinux, vmlinux.sym & fprom files
-			(prom simulations)
-				worktree
-				worktree/stand/arcs/IP37prom/dev
-				any directory with fw.bin & fw.sim files
-
-    Simulations:
-	sim  [-X <n>] [-o <output>] [-M] [<config_file>]
-		-c<cf>	Control file name				[Default: cf]
-		-M	Pipe output thru fmtmedusa
-		-o	Output filename (copy of all commands/output)	[Default: simout]
-		-X	Specifies number of instructions to execute	[Default: 0]
-			(Used only in auto test mode - not described here)
-
-Examples:
-	sim -p <promtree>	# create control file (cf) & links for prom simulations
-	sim -k <linuxtree>	# create control file (cf) & links for linux simulations
-	sim -p -c cfprom	# create a prom control file (cfprom) only. No links are made.
-
-	sim			# run medusa using previously created links &
-				#   control file (cf).
-END
-exit 1
-}
-
-# ----------------------- create control file header --------------------
-create_cf_header() {
-cat <<END >>$CF
-#
-# Template for a control file for running linux kernels under medusa. 
-# You probably want to make mods here but this is a good starting point.
-#
-
-# Preferences
-setenv cpu_stepping A
-setenv exceptionPrint off
-setenv interrupt_messages off
-setenv lastPCsize 100000
-setenv low_power_mode on
-setenv partialIntelChipSet on
-setenv printIntelMessages off
-setenv prom_write_action halt
-setenv prom_write_messages on
-setenv step_quantum 100
-setenv swizzling on
-setenv tsconsole on
-setenv uart_echo on
-symbols on
-
-# IDE disk params
-setenv diskCylinders 611
-setenv bootDrive C
-setenv diskHeads 16
-setenv diskPath idedisk
-setenv diskPresent 1
-setenv diskSpt 63
-
-# Hardware config
-setenv coherency_type nasid
-setenv cpu_cache_type default
-setenv synergy_cache_type syn_cac_64m_8w
-setenv l4_uc_snoop off
-
-# Numalink config
-setenv route_enable on
-setenv network_type router		# Select [xbar|router]
-setenv network_warning 0xff
-
-END
-}
-
-
-# ------------------ create control file entries for linux simulations -------------
-create_cf_linux() {
-cat <<END >>$CF
-# Kernel specific options
-setenv calias_size 0
-setenv mca_on_memory_failure off
-setenv LOADPC 0x00100000		# FPROM load address/entry point (8 digits!)
-setenv symbol_table vmlinux.sym
-load fprom
-load vmlinux
-
-# Useful breakpoints to always have set. Add more if desired.
-break 0xe000000000505e00	all	# dispatch_to_fault_handler
-break panic			all	# stop on panic
-break die_if_kernel		all	# may as well stop
-
-END
-}
-
-# ------------------ create control file entries for prom simulations ---------------
-create_cf_prom() {
-	SYM2=""
-	ADDR="0x80000000ff800000"
-	[ "$EMBEDDED_LINUX" != "0" ] || SYM2="setenv symbol_table2 vmlinux.sym"
-	[ "$SIZE" = "8MB" ] || ADDR="0x80000000ffc00000"
-	cat <<END >>$CF
-# PROM specific options
-setenv mca_on_memory_failure on
-setenv LOADPC 0x80000000ffffffb0
-setenv promFile fw.bin
-setenv promAddr $ADDR
-setenv symbol_table fw.sym
-$SYM2
-
-# Useful breakpoints to always have set. Add more if desired.
-break ivt_gexx 		all
-break ivt_brk		all
-break PROM_Panic_Spin	all
-break PROM_Panic	all
-break PROM_C_Panic	all
-break fled_die		all
-break ResetNow		all
-break zzzbkpt		all
-
-END
-}
-
-
-# ------------------ create control file entries for memory configuration -------------
-create_cf_memory() {
-cat <<END >>$CF
-# CPU/Memory map format:
-#	setenv nodeN_memory_config 0xBSBSBSBS
-#		B=banksize (0=unused, 1=64M, 2=128M, .., 5-1G, c=8M, d=16M, e=32M)
-#		S=bank enable (0=both disable, 3=both enable, 2=bank1 enable, 1=bank0 enable)
-#		  rightmost digits are for bank 0, the lowest address.
-#	setenv nodeN_nasid <nasid>
-#		specifies the NASID for the node. This is used ONLY if booting the kernel.
-#		On PROM configurations, set to 0 - PROM will change it later.
-#	setenv nodeN_cpu_config <cpu_mask>
-#		Set bit number N to 1 to enable cpu N. Ex., a value of 5 enables cpu 0 & 2.
-#
-# Repeat the above 3 commands for each node.
-#
-# For kernel, default to 32MB. Although this is not a valid hardware configuration,
-# it runs faster on medusa. For PROM, 64MB is smallest allowed value.
-
-setenv node0_cpu_config		0x1	# Enable only cpu 0 on the node
-END
-
-if [ $LINUX -eq 1 ] ; then
-cat <<END >>$CF
-setenv node0_nasid		0	# cnode 0 has NASID 0
-setenv node0_memory_config 	0xe1	# 32MB
-END
-else
-cat <<END >>$CF
-setenv node0_memory_config 	0x31	# 256MB
-END
-fi
-}
-
-# -------------------- set links to linux files -------------------------
-set_linux_links() {
-	if [ -d $D/linux/arch ] ; then
-		D=$D/linux
-	elif [ -d $D/arch -o -e vmlinux.sym -o -e $D/vmlinux ] ; then
-		D=$D
-	else
-		err "cant determine directory for linux binaries"
-	fi
-	rm -rf vmlinux vmlinux.sym fprom
-	ln -s $D/vmlinux vmlinux
-	if [ -f $D/vmlinux.sym ] ; then
-		ln -s $D/vmlinux.sym vmlinux.sym
-	elif  [ -f $D/System.map ] ; then
-		ln -s $D/System.map vmlinux.sym
-	fi
-	if [ -d $D/arch ] ; then
-		ln -s $D/arch/ia64/sn/fprom/fprom fprom
-	else
-		ln -s $D/fprom fprom
-	fi
-	echo "  .. Created links to linux files"	
-}
-
-# -------------------- set links to prom files -------------------------
-set_prom_links() {
-	if [ -d $D/stand ] ; then
-		D=$D/stand/arcs/IP37prom/dev
-	elif [ -d $D/sal ] ; then
-		D=$D
-	else
-		err "cant determine directory for PROM binaries"
-	fi
-	SETUP="/tmp/tmp.$$"
-	rm -r -f $SETUP
-	sed 's/export/setenv/' < $D/../../../../.setup | sed 's/=/ /' >$SETUP
-	egrep -q '^ *setenv *PROMSIZE *8MB|^ *export' $SETUP
-	if [ $? -eq 0 ] ; then
-		SIZE="8MB"
-	else
-		SIZE="4MB"
-	fi
-	grep -q '^ *setenv *LAUNCH_VMLINUX' $SETUP
-	EMBEDDED_LINUX=$?
-	PRODUCT=`grep '^ *setenv *PRODUCT' $SETUP | cut -d" " -f3`
-	rm -f fw.bin fw.map fw.sym vmlinux vmlinux.sym fprom $SETUP
-	SDIR="${PRODUCT}${SIZE}.O"
-	BIN="${PRODUCT}ip37prom${SIZE}"
-	ln -s $D/$SDIR/$BIN.bin fw.bin
-	ln -s $D/$SDIR/$BIN.map fw.map
-	ln -s $D/$SDIR/$BIN.sym fw.sym
-	echo "  .. Created links to $SIZE prom files"
-	if [ $EMBEDDED_LINUX -eq 0 ] ; then
-		ln -s $D/linux/vmlinux vmlinux
-		ln -s $D/linux/vmlinux.sym vmlinux.sym
-		if [ -d linux/arch ] ; then
-			ln -s $D/linux/arch/ia64/sn/fprom/fprom fprom
-		else
-			ln -s $D/linux/fprom fprom
-		fi
-		echo "  .. Created links to embedded linux files in prom tree"
-	fi
-}
-
-# --------------- start of shell script --------------------------------
-OUT="simout"
-FMTMED=0
-STEPCNT=0
-PROM=0
-LINUX=0
-NCF="cf"
-while getopts "HMX:c:o:pk" c ; do
-        case ${c} in
-                H) help;;
-		M) FMTMED=1;;
-		X) STEPCNT=${OPTARG};;
-		c) NCF=${OPTARG};;
-		k) PROM=0;LINUX=1;;
-		p) PROM=1;LINUX=0;;
-		o) OUT=${OPTARG};;
-                \?) exit 1;;
-        esac
-done
-shift `expr ${OPTIND} - 1`
-
-# Check if command is for creating control file and/or links to images.
-if [ $PROM -eq 1 -o $LINUX -eq 1 ] ; then
-	CF=$NCF
-	[ ! -f $CF ] || err "wont overwrite an existing control file ($CF)"
-	if [ $# -gt 0 ] ; then
-		D=$1
-		[ -d $D ] || err "cannot find directory $D"
-		[ $PROM -eq 0 ]  || set_prom_links
-		[ $LINUX -eq 0 ] || set_linux_links
-	fi
-	create_cf_header
-	[ $PROM -eq 0 ]  || create_cf_prom
-	[ $LINUX -eq 0 ] || create_cf_linux
-	[ ! -f ../idedisk ] || ln -s ../idedisk .
-	create_cf_memory
-	echo "  .. Basic control file created (in $CF). You might want to edit"
-	echo "     this file (at least, look at it)."
-	exit 0
-fi
-
-# Verify that the control file exists
-CF=${1:-$NCF}
-[ -f $CF ] || err "No control file exists. For help, type: $0 -H"
-
-# Build the .cf files from the user control file. The .cf file is
-# identical except that the actual start & load addresses are inserted
-# into the file. In addition, the FPROM commands for configuring memory
-# and LIDs are generated. 
-
-rm -f .cf .cf1 .cf2
-awk '
-function strtonum(n) {
-	 if (substr(n,1,2) != "0x")
-	 	return int(n)
-	 n = substr(n,3)
-	 r=0
-	 while (length(n) > 0) {
-	 	r = r*16+(index("0123456789abcdef", substr(n,1,1))-1)
-		n = substr(n,2)
-	 }
-	 return r
-	}
-/^#/   	{next}
-/^$/	{next}
-/^setenv *LOADPC/               {loadpc = $3; next}
-/^setenv *node.._cpu_config/	{n=int(substr($2,5,2)); cpuconf[n] = strtonum($3); print; next}
-/^setenv *node.._memory_config/	{n=int(substr($2,5,2)); memconf[n] = strtonum($3); print; next}
-/^setenv *node.._nasid/		{n=int(substr($2,5,2)); nasid[n] = strtonum($3); print; next}
-/^setenv *node._cpu_config/	{n=int(substr($2,5,1)); cpuconf[n] = strtonum($3); print; next}
-/^setenv *node._memory_config/	{n=int(substr($2,5,1)); memconf[n] = strtonum($3); print; next}
-/^setenv *node._nasid/		{n=int(substr($2,5,1)); nasid[n] = strtonum($3); print; next}
-		{print}
-END	{
-	 # Generate the memmap info that starts at the beginning of
-	 # the node the kernel was loaded on.
-	 loadnasid = nasid[0]
-	 cnode = 0
-	 for (i=0; i<128; i++) {
-		if (memconf[i] != "") {
-			printf "sm 0x%x%08x 0x%x%04x%04x\n", 
-				2*loadnasid, 8*cnodes+8, memconf[i], cpuconf[i], nasid[i]
-			cnodes++
-			cpus += substr("0112122312232334", cpuconf[i]+1,1)
-		}
-	 }
-	 printf "sm 0x%x00000000 0x%x%08x\n", 2*loadnasid, cnodes, cpus
-	 printf "setenv number_of_nodes %d\n", cnodes
-
-	 # Now set the starting PC for each cpu.
-	 cnode = 0
-	 lowcpu=-1
-	 for (i=0; i<128; i++) {
-		if (memconf[i] != "") {
-			printf "setnode %d\n", cnode
-			conf = cpuconf[i]
-			for (j=0; j<4; j++) {
-				if (conf != int(conf/2)*2) {
-	 				printf "setcpu %d\n", j
-					if (length(loadpc) == 18)
-						printf "sr pc %s\n", loadpc
-					else
-						printf "sr pc 0x%x%s\n", 2*loadnasid, substr(loadpc,3)
-					if (lowcpu == -1)
-						lowcpu = j
-				}
-				conf = int(conf/2)
-			}
-			cnode++
-		}
-	 }
-	 printf "setnode 0\n"
-	 printf "setcpu %d\n", lowcpu
-	}
-' <$CF >.cf
-
-# Now build the .cf1 & .cf2 control files.
-CF2_LINES="^sm |^break |^run |^si |^quit |^symbols "
-egrep  "$CF2_LINES" .cf >.cf2
-egrep -v "$CF2_LINES" .cf >.cf1
-if [ $STEPCNT -ne 0 ] ; then
-	echo "s $STEPCNT" >>.cf2
-	echo "lastpc 1000" >>.cf2
-	echo "q" >>.cf2
-fi
-if [ -f vmlinux.sym ] ; then
-	awk '/ _start$/ {print "sr g 9 0x" $3}' < vmlinux.sym >> .cf2
-fi
-echo "script-on $OUT" >>.cf2
-
-# Now start medusa....
-if [ $FMTMED -ne 0 ] ; then
-	$MEDUSA -system mpsn1 -c .cf1 -i .cf2 |  fmtmedusa
-elif [ $STEPCNT -eq 0 ] ; then
-	$MEDUSA -system mpsn1 -c .cf1 -i .cf2 
-else
-	$MEDUSA -system mpsn1 -c .cf1 -i .cf2 2>&1 
-fi
diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c
--- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2004-06-07 08:45:20 -07:00
+++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2004-08-18 09:38:41 -07:00
@@ -290,6 +290,7 @@
 			addr |= __IA64_UNCACHED_OFFSET;
 			dev->resource[idx].start = addr;
 			dev->resource[idx].end = addr + size;
+			dev->resource[idx].parent = &ioport_resource;
 		}
 
 		if (dev->resource[idx].flags & IORESOURCE_IO)
@@ -322,6 +323,7 @@
 			addr |= __IA64_UNCACHED_OFFSET;
 			dev->resource[idx].start = addr;
 			dev->resource[idx].end = addr + size;
+			dev->resource[idx].parent = &iomem_resource;
 		}
 
 		if (dev->resource[idx].flags & IORESOURCE_MEM)
@@ -351,6 +353,7 @@
                         addr |= __IA64_UNCACHED_OFFSET;
                         dev->resource[PCI_ROM_RESOURCE].start = addr;
                         dev->resource[PCI_ROM_RESOURCE].end = addr + size;
+			dev->resource[idx].parent = &iomem_resource;
                         if (dev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_MEM)
                                 cmd |= PCI_COMMAND_MEMORY;
                 }
diff -Nru a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
--- a/arch/ia64/sn/kernel/bte.c	2004-07-30 14:05:59 -07:00
+++ b/arch/ia64/sn/kernel/bte.c	2004-08-18 10:00:28 -07:00
@@ -421,9 +421,10 @@
 	mynodepda->bte_recovery_timer.data = (unsigned long) mynodepda;
 
 	for (i = 0; i < BTES_PER_NODE; i++) {
-		(u64) mynodepda->bte_if[i].bte_base_addr =
-		    REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode),
-			(i == 0 ? IIO_IBLS0 : IIO_IBLS1));
+		/* Which link status register should we use? */
+		unsigned long link_status = (i == 0 ? IIO_IBLS0 : IIO_IBLS1);
+		mynodepda->bte_if[i].bte_base_addr = (u64 *)
+			REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), link_status);
 
 		/*
 		 * Initialize the notification and spinlock
diff -Nru a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2004-03-23 06:36:53 -08:00
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2004-08-18 11:00:37 -07:00
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
  */
 #include <linux/config.h>
 #include <asm/uaccess.h>
@@ -118,11 +118,33 @@
 	}
 }
 
+static int coherence_id_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+	return sprintf(page, "%d\n", cpuid_to_coherence_id(smp_processor_id()));
+}
+
+void
+register_sn_coherence_id(void) {
+	struct proc_dir_entry *entry;
+
+	if (!sgi_proc_dir) {
+		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+	}
+	entry = create_proc_entry("coherence_id", 0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = coherence_id_read_proc;
+		entry->write_proc = NULL;
+	}
+}
+
 void
 register_sn_procfs(void) {
 	register_sn_partition_id();
 	register_sn_serial_numbers();
 	register_sn_force_interrupt();
+	register_sn_coherence_id();
 }
 
 #endif /* CONFIG_PROC_FS */
diff -Nru a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
--- a/arch/m68k/kernel/process.c	2004-06-17 23:41:39 -07:00
+++ b/arch/m68k/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -232,7 +232,7 @@
 	child_tidptr = (int *)regs->d4;
 	if (!newsp)
 		newsp = rdusp();
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0,
+	return do_fork(clone_flags, newsp, regs, 0,
 		       parent_tidptr, child_tidptr);
 }
 
diff -Nru a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
--- a/arch/m68k/kernel/signal.c	2004-07-28 21:58:40 -07:00
+++ b/arch/m68k/kernel/signal.c	2004-08-25 17:37:25 -07:00
@@ -842,9 +842,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
@@ -925,9 +923,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
diff -Nru a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
--- a/arch/m68k/kernel/time.c	2004-04-08 01:38:42 -07:00
+++ b/arch/m68k/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -38,24 +38,6 @@
   return -1;
 }
 
-static inline void do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		if (pc < prof_len)
-			++prof_buffer[pc];
-		else
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			++prof_buffer[prof_len-1];
-	}
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -63,9 +45,7 @@
 static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 {
 	do_timer(regs);
-
-	if (!user_mode(regs))
-		do_profile(regs->pc);
+	profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
 	/* use power LED as a heartbeat instead -- much more useful
diff -Nru a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
--- a/arch/m68k/kernel/vmlinux-std.lds	2004-04-04 03:11:21 -07:00
+++ b/arch/m68k/kernel/vmlinux-std.lds	2004-08-24 02:08:55 -07:00
@@ -51,9 +51,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init)
diff -Nru a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
--- a/arch/m68k/kernel/vmlinux-sun3.lds	2004-04-04 03:11:21 -07:00
+++ b/arch/m68k/kernel/vmlinux-sun3.lds	2004-08-24 02:08:55 -07:00
@@ -45,9 +45,6 @@
 	__setup_start = .;
 	.init.setup : { *(.init.setup) }
 	__setup_end = .;
-	__start___param = .;
-	__param : { *(__param) }
-	__stop___param = .;
 	__initcall_start = .;
 	.initcall.init : {
 		*(.initcall1.init)
diff -Nru a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
--- a/arch/m68knommu/kernel/process.c	2004-05-10 04:25:34 -07:00
+++ b/arch/m68knommu/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -188,7 +188,7 @@
 	newsp = regs->d2;
 	if (!newsp)
 		newsp = rdusp();
-        return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+        return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 }
 
 int copy_thread(int nr, unsigned long clone_flags,
diff -Nru a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
--- a/arch/m68knommu/kernel/signal.c	2004-02-18 16:43:09 -08:00
+++ b/arch/m68knommu/kernel/signal.c	2004-08-25 17:37:25 -07:00
@@ -616,9 +616,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
@@ -685,9 +683,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
diff -Nru a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
--- a/arch/m68knommu/kernel/time.c	2004-02-18 19:43:10 -08:00
+++ b/arch/m68knommu/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -41,24 +41,6 @@
 	return -1;
 }
 
-static inline void do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		if (pc < prof_len)
-			++prof_buffer[pc];
-		else
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			++prof_buffer[prof_len-1];
-	}
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -75,9 +57,8 @@
 	write_seqlock(&xtime_lock);
 
 	do_timer(regs);
-
-	if (!user_mode(regs))
-		do_profile(regs->pc);
+	if (current->pid)
+		profile_tick(CPU_PROFILING, regs);
 
 	/*
 	 * If we have an externally synchronized Linux clock, then update
diff -Nru a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
--- a/arch/m68knommu/kernel/vmlinux.lds.S	2004-04-12 10:55:06 -07:00
+++ b/arch/m68knommu/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -284,9 +284,6 @@
 		__setup_start = .;
 		*(.init.setup)
 		__setup_end = .;
-		__start___param = .;
-		*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 		*(.initcall1.init)
 		*(.initcall2.init)
diff -Nru a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
--- a/arch/m68knommu/platform/5307/timers.c	2004-04-12 10:55:08 -07:00
+++ b/arch/m68knommu/platform/5307/timers.c	2004-08-26 23:30:31 -07:00
@@ -110,17 +110,8 @@
 {
 	/* Reset ColdFire timer2 */
 	mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-
-        if (!user_mode(regs)) {
-                if (prof_buffer && current->pid) {
-                        extern int _stext;
-                        unsigned long ip = instruction_pointer(regs);
-                        ip -= (unsigned long) &_stext;
-                        ip >>= prof_shift;
-                        if (ip < prof_len)
-                                prof_buffer[ip]++;
-                }
-        }
+	if (current->pid)
+		profile_tick(CPU_PROFILING, regs);
 }
 
 /***************************************************************************/
diff -Nru a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
--- a/arch/mips/kernel/irixsig.c	2004-05-29 02:13:12 -07:00
+++ b/arch/mips/kernel/irixsig.c	2004-08-25 17:37:25 -07:00
@@ -121,9 +121,7 @@
 	return;
 
 segv_and_exit:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 
 static void inline
diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
--- a/arch/mips/kernel/irq.c	2004-06-24 01:55:53 -07:00
+++ b/arch/mips/kernel/irq.c	2004-08-26 23:30:30 -07:00
@@ -872,30 +872,6 @@
 
 #endif
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data, new_value;
-	unsigned long full_count = count, err;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -931,26 +907,15 @@
 #endif
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", 0);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-	    return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff -Nru a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
--- a/arch/mips/kernel/signal.c	2004-05-10 04:25:30 -07:00
+++ b/arch/mips/kernel/signal.c	2004-08-25 17:37:25 -07:00
@@ -406,9 +406,7 @@
         return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 #endif
 
@@ -475,9 +473,7 @@
 	return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 
 extern void setup_rt_frame_n32(struct k_sigaction * ka,
diff -Nru a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
--- a/arch/mips/kernel/signal32.c	2004-05-10 04:25:30 -07:00
+++ b/arch/mips/kernel/signal32.c	2004-08-25 17:37:26 -07:00
@@ -574,9 +574,7 @@
         return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 
 static inline void setup_rt_frame(struct k_sigaction * ka,
@@ -647,9 +645,7 @@
 	return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 
 static inline void handle_signal(unsigned long sig, siginfo_t *info,
diff -Nru a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
--- a/arch/mips/kernel/signal_n32.c	2004-05-10 04:25:30 -07:00
+++ b/arch/mips/kernel/signal_n32.c	2004-08-25 17:37:26 -07:00
@@ -208,7 +208,5 @@
 	return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
diff -Nru a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
--- a/arch/mips/kernel/smp.c	2004-05-10 04:25:47 -07:00
+++ b/arch/mips/kernel/smp.c	2004-08-24 02:08:12 -07:00
@@ -254,16 +254,6 @@
 	cpu_set(0, cpu_callin_map);
 }
 
-static struct task_struct * __init fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/*
-	 * don't care about the eip and regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 /*
  * Startup the CPU with this logical number
  */
@@ -275,19 +265,9 @@
 	 * The following code is purely to make sure
 	 * Linux can schedule processes on this slave.
 	 */
-	idle = fork_by_hand();
+	idle = fork_idle(cpu);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d\n", cpu);
-
-	wake_up_forked_process(idle);
-
-	/*
-	 * We remove it from the pidhash and the runqueue once we've
-	 * got the process:
-	 */
-	init_idle(idle, cpu);
-
-	unhash_process(idle);
 
 	prom_boot_secondary(cpu, idle);
 
diff -Nru a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
--- a/arch/mips/kernel/syscall.c	2004-06-24 01:55:59 -07:00
+++ b/arch/mips/kernel/syscall.c	2004-08-24 02:08:42 -07:00
@@ -180,7 +180,7 @@
 		newsp = regs.regs[29];
 	parent_tidptr = (int *) regs.regs[6];
 	child_tidptr = (int *) regs.regs[7];
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+	return do_fork(clone_flags, newsp, &regs, 0,
 	               parent_tidptr, child_tidptr);
 }
 
diff -Nru a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
--- a/arch/mips/kernel/time.c	2004-06-24 01:55:59 -07:00
+++ b/arch/mips/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -417,23 +417,8 @@
  */
 void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	if (!user_mode(regs)) {
-		if (prof_buffer && current->pid) {
-			unsigned long pc = regs->cp0_epc;
-
-			pc -= (unsigned long) _stext;
-			pc >>= prof_shift;
-			/*
-			 * Dont ignore out-of-bounds pc values silently,
-			 * put them into the last histogram slot, so if
-			 * present, they will show up as a sharp peak.
-			 */
-			if (pc > prof_len - 1)
-				pc = prof_len - 1;
-			atomic_inc((atomic_t *)&prof_buffer[pc]);
-		}
-	}
-
+	if (current->pid)
+		profile_tick(CPU_PROFILING, regs);
 #ifdef CONFIG_SMP
 	/* in UP mode, update_process_times() is invoked by do_timer() */
 	update_process_times(user_mode(regs));
diff -Nru a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
--- a/arch/mips/kernel/vmlinux.lds.S	2004-04-12 10:53:59 -07:00
+++ b/arch/mips/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -96,9 +96,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
 
   .early_initcall.init : {
   __earlyinitcall_start = .;
diff -Nru a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
--- a/arch/mips/sgi-ip27/ip27-memory.c	2004-04-19 23:53:22 -07:00
+++ b/arch/mips/sgi-ip27/ip27-memory.c	2004-08-24 02:08:33 -07:00
@@ -225,7 +225,7 @@
 		pfn_t end_pfn = node_getmaxclick(node) + 1;
 
 		zones_size[ZONE_DMA] = end_pfn - start_pfn;
-		free_area_init_node(node, NODE_DATA(node), NULL,
+		free_area_init_node(node, NODE_DATA(node),
 				zones_size, start_pfn, NULL);
 
 		if (end_pfn > max_low_pfn)
diff -Nru a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
--- a/arch/parisc/kernel/hardware.c	2004-08-13 01:21:43 -07:00
+++ b/arch/parisc/kernel/hardware.c	2004-08-24 02:09:07 -07:00
@@ -7,7 +7,7 @@
  *    Reference Specification", March 7, 1999, version 0.96.  This
  *    is available at http://parisc-linux.org/documentation/
  *
- *    Copyright 1999 by Alex deVries <adevries@thepuffingroup.com>
+ *    Copyright 1999 by Alex deVries <alex@onefishtwo.ca>
  *    and copyright 1999 The Puffin Group Inc.
  *
  *    This program is free software; you can redistribute it and/or modify
diff -Nru a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
--- a/arch/parisc/kernel/process.c	2004-08-13 01:21:43 -07:00
+++ b/arch/parisc/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -262,7 +262,7 @@
 	if(usp == 0)
 		usp = regs->gr[30];
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, user_tid, NULL);
+	return do_fork(clone_flags, usp, regs, 0, user_tid, NULL);
 }
 
 int
diff -Nru a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
--- a/arch/parisc/kernel/smp.c	2004-08-13 01:21:44 -07:00
+++ b/arch/parisc/kernel/smp.c	2004-08-27 14:30:55 -07:00
@@ -486,24 +486,6 @@
 }
 
 /*
- * Create the idle task for a new Slave CPU.  DO NOT use kernel_thread()
- * because that could end up calling schedule(). If it did, the new idle
- * task could get scheduled before we had a chance to remove it from the
- * run-queue...
- */
-static struct task_struct *fork_by_hand(void)
-{
-	struct pt_regs regs;  
-
-	/*
-	 * don't care about the regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
-
-/*
  * Bring one cpu online.
  */
 int __init smp_boot_one_cpu(int cpuid)
@@ -521,13 +503,10 @@
 	 * Sheesh . . .
 	 */
 
-	idle = fork_by_hand();
+	idle = fork_idle(cpuid);
 	if (IS_ERR(idle))
 		panic("SMP: fork failed for CPU:%d", cpuid);
 
-	wake_up_forked_process(idle);
-	init_idle(idle, cpuid);
-	unhash_process(idle);
 	idle->thread_info->cpu = cpuid;
 
 	/* Let _start know what logical CPU we're booting
diff -Nru a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
--- a/arch/parisc/kernel/time.c	2004-02-18 19:43:10 -08:00
+++ b/arch/parisc/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -47,44 +47,6 @@
 extern void smp_do_timer(struct pt_regs *regs);
 #endif
 
-static inline void
-parisc_do_profile(struct pt_regs *regs)
-{
-	unsigned long pc = regs->iaoq[0];
-#if 0
-	extern unsigned long prof_cpu_mask;
-#endif
-	extern char _stext;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-#if 0
-	/* FIXME: when we have irq affinity to cpu, we need to
-	 * only look at the cpus specified in this mask 
-	 */
-
-	if (!((1 << smp_processor_id()) & prof_cpu_mask))
-		return;
-#endif
-
-	pc -= (unsigned long) &_stext;
-	pc >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds PC values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (pc > prof_len - 1)
-		pc = prof_len - 1;
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	long now;
@@ -92,7 +54,7 @@
 	int nticks;
 	int cpu = smp_processor_id();
 
-	parisc_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 
 	now = mfctl(16);
 	/* initialize next_tick to time at last clocktick */
diff -Nru a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
--- a/arch/parisc/kernel/vmlinux.lds.S	2004-05-10 02:18:39 -07:00
+++ b/arch/parisc/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -130,9 +130,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff -Nru a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
--- a/arch/parisc/mm/init.c	2004-08-13 01:21:44 -07:00
+++ b/arch/parisc/mm/init.c	2004-08-24 02:08:33 -07:00
@@ -804,7 +804,7 @@
 		   ZONE_DMA zone. */
 		zones_size[ZONE_DMA] = pmem_ranges[i].pages;
 
-		free_area_init_node(i,NODE_DATA(i),NULL,zones_size,
+		free_area_init_node(i, NODE_DATA(i), zones_size,
 				pmem_ranges[i].start_pfn, 0);
 
 #ifdef CONFIG_DISCONTIGMEM
diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
--- a/arch/ppc/8xx_io/uart.c	2004-07-15 16:26:09 -07:00
+++ b/arch/ppc/8xx_io/uart.c	2004-08-24 02:08:52 -07:00
@@ -2592,7 +2592,7 @@
 		state->icount.rx = state->icount.tx = 0;
 		state->icount.frame = state->icount.parity = 0;
 		state->icount.overrun = state->icount.brk = 0;
-		printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n",
+		printk(KERN_INFO "ttyS%d at 0x%04x is a %s\n",
 		       i, (unsigned int)(state->port),
 		       (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC");
 #ifdef CONFIG_SERIAL_CONSOLE
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	2004-08-15 12:45:18 -07:00
+++ b/arch/ppc/Kconfig	2004-08-24 12:40:55 -07:00
@@ -685,7 +685,8 @@
 
 config PPC_GEN550
 	bool
-	depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || PRPMC750 || K2 || PRPMC800
+	depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || \
+		PRPMC750 || K2 || PRPMC800 || LOPEC
 	default y
 
 config FORCE
@@ -811,10 +812,6 @@
 config HIGHMEM
 	bool "High memory support"
 
-config KERNEL_ELF
-	bool
-	default y
-
 source "fs/Kconfig.binfmt"
 
 config PROC_DEVICETREE
@@ -832,10 +829,11 @@
 	  Some PReP systems have residual data passed to the kernel by the
 	  firmware.  This allows detection of memory size, devices present and
 	  other useful pieces of information.  Sometimes this information is
-	  not present or incorrect.
+	  not present or incorrect, in which case it could lead to the machine 
+	  behaving incorrectly.  If this happens, either disable PREP_RESIDUAL
+	  or pass the 'noresidual' option to the kernel.
 
-	  Unless you expect to boot on a PReP system, there is no need to
-	  select Y.
+	  If you are running a PReP system, say Y here, otherwise say N.
 
 config PROC_PREPRESIDUAL
 	bool "Support for reading of PReP Residual Data in /proc"
diff -Nru a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
--- a/arch/ppc/Kconfig.debug	2004-08-15 12:45:31 -07:00
+++ b/arch/ppc/Kconfig.debug	2004-08-24 02:08:10 -07:00
@@ -53,6 +53,18 @@
 	  Unless you are intending to debug the kernel with one of these
 	  machines, say N here.
 
+config SCHEDSTATS
+	bool "Collect scheduler statistics"
+	depends on DEBUG_KERNEL && PROC_FS
+	help
+	  If you say Y here, additional code will be inserted into the
+	  scheduler and related routines to collect statistics about
+	  scheduler behavior and provide them in /proc/schedstat.  These
+	  stats may be useful for both tuning and debugging the scheduler
+	  If you aren't debugging the scheduler or trying to tune a specific
+	  application, you can say N to avoid the very slight overhead
+	  this adds.
+
 config BOOTX_TEXT
 	bool "Support for early boot text console (BootX or OpenFirmware only)"
 	depends PPC_OF
diff -Nru a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
--- a/arch/ppc/amiga/config.c	2003-09-12 09:26:51 -07:00
+++ b/arch/ppc/amiga/config.c	2004-08-16 09:04:08 -07:00
@@ -423,9 +423,6 @@
   mach_floppy_setup    = amiga_floppy_setup;
 #endif
   mach_reset           = amiga_reset;
-#ifdef CONFIG_DUMMY_CONSOLE
-  conswitchp           = &dummy_con;
-#endif
 #ifdef CONFIG_HEARTBEAT
   mach_heartbeat = amiga_heartbeat;
 #endif
diff -Nru a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
--- a/arch/ppc/boot/common/misc-common.c	2004-07-29 08:17:44 -07:00
+++ b/arch/ppc/boot/common/misc-common.c	2004-08-25 08:29:09 -07:00
@@ -526,6 +526,11 @@
  * on others it's an offset from a given location. -- Tom
  */
 
+void ISA_init(unsigned long base)
+{
+	ISA_io = (unsigned char *)base;
+}
+
 void
 outb(int port, unsigned char val)
 {
diff -Nru a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c
--- a/arch/ppc/boot/common/serial_stub.c	2003-06-28 01:07:35 -07:00
+++ b/arch/ppc/boot/common/serial_stub.c	2004-08-25 08:29:09 -07:00
@@ -11,11 +11,6 @@
  * is" without any warranty of any kind, whether express or implied.
  */
 
-void __attribute__ ((weak))
-serial_fixups(void)
-{
-}
-
 unsigned long __attribute__ ((weak))
 serial_init(int chan, void *ignored)
 {
diff -Nru a/arch/ppc/boot/include/nonstdio.h b/arch/ppc/boot/include/nonstdio.h
--- a/arch/ppc/boot/include/nonstdio.h	2002-11-07 03:31:11 -08:00
+++ b/arch/ppc/boot/include/nonstdio.h	2004-08-25 08:29:09 -07:00
@@ -30,3 +30,5 @@
 extern void puts(const char *);
 extern void udelay(long delay);
 extern unsigned char inb(int port);
+extern void board_isa_init(void);
+extern void ISA_init(unsigned long base);
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	2004-07-29 08:17:44 -07:00
+++ b/arch/ppc/boot/simple/Makefile	2004-08-25 08:29:09 -07:00
@@ -73,7 +73,7 @@
 zimageinitrd-$(CONFIG_GEMINI)		:= zImage.initrd-STRIPELF
          end-$(CONFIG_GEMINI)		:= gemini
 
-     extra.o-$(CONFIG_K2)		:= legacy.o
+     extra.o-$(CONFIG_K2)		:= prepmap.o
          end-$(CONFIG_K2)		:= k2
    cacheflag-$(CONFIG_K2)		:= -include $(clear_L2_L3)
 
@@ -89,7 +89,7 @@
          end-$(motorola)		:= pplus
 
 # Overrides previous assingment
-     extra.o-$(CONFIG_PPLUS)		:= legacy.o
+     extra.o-$(CONFIG_PPLUS)		:= prepmap.o
      extra.o-$(CONFIG_LOPEC)		:= mpc10x_memory.o
 
       zimage-$(pcore)			:= zImage-STRIPELF
@@ -100,7 +100,7 @@
 
       zimage-$(CONFIG_PPC_PREP)		:= zImage-PPLUS
 zimageinitrd-$(CONFIG_PPC_PREP)		:= zImage.initrd-PPLUS
-     extra.o-$(CONFIG_PPC_PREP)		:= legacy.o
+     extra.o-$(CONFIG_PPC_PREP)		:= prepmap.o
         misc-$(CONFIG_PPC_PREP)		+= misc-prep.o mpc10x_memory.o
          end-$(CONFIG_PPC_PREP)		:= prep
 
diff -Nru a/arch/ppc/boot/simple/chrpmap.S b/arch/ppc/boot/simple/chrpmap.S
--- a/arch/ppc/boot/simple/chrpmap.S	2002-05-14 16:45:03 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,19 +0,0 @@
-/*
- * arch/ppc/boot/simple/chrpmap.S
- *
- * Author: Tom Rini <trini@mvista.com>
- *
- * This will go and setup ISA_io to 0xFE00000 and return.
- */
-
-#include <asm/ppc_asm.h>
-
-	.text
-
-	.globl serial_fixups
-serial_fixups:
-	lis	r3,ISA_io@h	/* Load ISA_io */
-	ori	r3,r3,ISA_io@l
-	lis	r4,0xFE00	/* Load the value, 0xFE00000 */
-	stw	r4,0(r3)	/* store */
-	blr
diff -Nru a/arch/ppc/boot/simple/chrpmap.c b/arch/ppc/boot/simple/chrpmap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/boot/simple/chrpmap.c	2004-08-25 08:29:09 -07:00
@@ -0,0 +1,12 @@
+/*
+ * 2004 (C) IBM. This file is licensed under the terms of the GNU General
+ * Public License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <nonstdio.h>
+
+void board_isa_init(void)
+{
+	ISA_init(0xFE000000);
+}
diff -Nru a/arch/ppc/boot/simple/legacy.S b/arch/ppc/boot/simple/legacy.S
--- a/arch/ppc/boot/simple/legacy.S	2002-05-14 16:45:03 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,19 +0,0 @@
-/*
- * arch/ppc/boot/simple/legacy.S
- *
- * Author: Tom Rini <trini@mvista.com>
- *
- * This will go and setup ISA_io to 0x8000000 and return.
- */
-
-#include <asm/ppc_asm.h>
-
-	.text
-
-	.globl serial_fixups
-serial_fixups:
-	lis	r3,ISA_io@h	/* Load ISA_io */
-	ori	r3,r3,ISA_io@l
-	lis	r4,0x8000	/* Load the value, 0x8000000 */
-	stw	r4,0(r3)	/* store */
-	blr
diff -Nru a/arch/ppc/boot/simple/misc-embedded.c b/arch/ppc/boot/simple/misc-embedded.c
--- a/arch/ppc/boot/simple/misc-embedded.c	2004-07-27 14:46:37 -07:00
+++ b/arch/ppc/boot/simple/misc-embedded.c	2004-08-03 11:01:47 -07:00
@@ -72,6 +72,14 @@
 extern void gunzip(void *, int, unsigned char *, int *);
 extern void embed_config(bd_t **bp);
 
+/* Weak function for boards which don't need to build the
+ * board info struct because they are using PPCBoot/U-Boot.
+ */
+void __attribute__ ((weak))
+embed_config(bd_t **bdp)
+{
+}
+
 unsigned long
 load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
 {
diff -Nru a/arch/ppc/boot/simple/misc-prep.c b/arch/ppc/boot/simple/misc-prep.c
--- a/arch/ppc/boot/simple/misc-prep.c	2004-03-01 15:34:28 -08:00
+++ b/arch/ppc/boot/simple/misc-prep.c	2004-08-25 08:29:09 -07:00
@@ -88,6 +88,7 @@
 		ofinit(OFW_interface);
 	}
 
+	board_isa_init();
 #if defined(CONFIG_VGA_CONSOLE)
 	vga_init((unsigned char *)0xC0000000);
 #endif /* CONFIG_VGA_CONSOLE */
diff -Nru a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c
--- a/arch/ppc/boot/simple/misc-spruce.c	2004-03-01 15:34:28 -08:00
+++ b/arch/ppc/boot/simple/misc-spruce.c	2004-08-25 08:29:09 -07:00
@@ -26,7 +26,6 @@
 /* Define some important locations of the Spruce. */
 #define SPRUCE_PCI_CONFIG_ADDR	0xfec00000
 #define SPRUCE_PCI_CONFIG_DATA	0xfec00004
-#define SPRUCE_ISA_IO_BASE	0xf8000000
 
 /* PCI configuration space access routines. */
 unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR;
@@ -85,8 +84,6 @@
 
 	out_le32((unsigned *)pci_config_data, val);
 }
-
-unsigned long isa_io_base = SPRUCE_ISA_IO_BASE;
 
 #define PCNET32_WIO_RDP		0x10
 #define PCNET32_WIO_RAP		0x12
diff -Nru a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
--- a/arch/ppc/boot/simple/misc.c	2004-07-26 11:41:48 -07:00
+++ b/arch/ppc/boot/simple/misc.c	2004-08-25 08:29:09 -07:00
@@ -97,7 +97,6 @@
 	struct bi_record *rec;
 	unsigned long initrd_loc, TotalMemory = 0;
 
-	serial_fixups();
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 	com_port = serial_init(0, NULL);
 #endif
@@ -268,10 +267,16 @@
 	return rec;
 }
 
+void __attribute__ ((weak))
+board_isa_init(void)
+{
+}
+
 /* Allow decompress_kernel to be hooked into.  This is the default. */
 void * __attribute__ ((weak))
 load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
 		void *ign1, void *ign2)
 {
+		board_isa_init();
 		return decompress_kernel(load_addr, num_words, cksum);
 }
diff -Nru a/arch/ppc/boot/simple/prepmap.c b/arch/ppc/boot/simple/prepmap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/boot/simple/prepmap.c	2004-08-25 08:29:10 -07:00
@@ -0,0 +1,12 @@
+/*
+ * 2004 (C) IBM. This file is licensed under the terms of the GNU General
+ * Public License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <nonstdio.h>
+
+void board_isa_init(void)
+{
+	ISA_init(0x80000000);
+}
diff -Nru a/arch/ppc/configs/mvme5100_defconfig b/arch/ppc/configs/mvme5100_defconfig
--- a/arch/ppc/configs/mvme5100_defconfig	2004-08-09 16:41:36 -07:00
+++ b/arch/ppc/configs/mvme5100_defconfig	2004-08-12 16:44:46 -07:00
@@ -4,23 +4,39 @@
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 
 #
 # Loadable module support
@@ -33,24 +49,26 @@
 CONFIG_KMOD=y
 
 #
-# Platform support
+# Processor
 #
-CONFIG_PPC=y
-CONFIG_PPC32=y
 CONFIG_6xx=y
 # CONFIG_40x is not set
+# CONFIG_44x is not set
 # CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
 # CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
 
 #
-# IBM 4xx options
+# Platform options
 #
-# CONFIG_8260 is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_STD_MMU=y
 # CONFIG_PPC_MULTIPLATFORM is not set
 # CONFIG_APUS is not set
-# CONFIG_WILLOW_2 is not set
+# CONFIG_WILLOW is not set
 # CONFIG_PCORE is not set
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
@@ -66,34 +84,31 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_LITE5200 is not set
 # CONFIG_MVME5100_IPMC761_PRESENT is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
-CONFIG_ALTIVEC=y
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
 
 #
-# General setup
+# Bus options
 #
-# CONFIG_HIGHMEM is not set
+CONFIG_GENERIC_ISA_DMA=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
 
 #
 # Advanced setup
@@ -110,14 +125,28 @@
 CONFIG_BOOT_LOAD=0x00800000
 
 #
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
 
 #
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -129,46 +158,46 @@
 # CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
 
 #
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
 CONFIG_BLK_DEV_IDE=y
 
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 # CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
 #
+CONFIG_IDE_GENERIC=y
 # CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
-# SCSI support
+# SCSI device support
 #
 CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
 
 #
 # SCSI support type (disk, tape, CD-ROM)
@@ -184,64 +213,69 @@
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 
 #
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-CONFIG_SCSI_SYM53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=32
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
@@ -251,6 +285,10 @@
 # CONFIG_I2O is not set
 
 #
+# Macintosh device drivers
+#
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -261,28 +299,33 @@
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 
 #
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
@@ -293,11 +336,13 @@
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_LIMIT=m
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
 CONFIG_IP_NF_MATCH_MAC=m
 CONFIG_IP_NF_MATCH_PKTTYPE=m
 CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
+# CONFIG_IP_NF_MATCH_RECENT is not set
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
 CONFIG_IP_NF_MATCH_AH_ESP=m
@@ -307,15 +352,15 @@
 CONFIG_IP_NF_MATCH_HELPER=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
 # CONFIG_IP_NF_NAT_LOCAL is not set
 # CONFIG_IP_NF_NAT_SNMP_BASIC is not set
 CONFIG_IP_NF_NAT_IRC=m
@@ -326,21 +371,24 @@
 CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
+# CONFIG_IP_NF_ARP_MANGLE is not set
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
 # CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -352,29 +400,33 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -389,10 +441,11 @@
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -403,6 +456,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -421,80 +475,91 @@
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_S2IO is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Token Ring devices
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
+# CONFIG_ISDN is not set
 
 #
-# Old CD-ROM drivers (not SCSI, not IDE)
+# Telephony Support
 #
-# CONFIG_CD_NO_IDESCSI is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
 #
-# CONFIG_INPUT is not set
+CONFIG_INPUT=y
 
 #
 # Userland interfaces
 #
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
 
 #
 # Input I/O drivers
 #
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
 
 #
 # Input Device Drivers
 #
-
-#
-# Macintosh device drivers
-#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
 
 #
 # Character devices
 #
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -502,6 +567,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -510,26 +576,8 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -551,11 +599,23 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
 
 #
 # Multimedia devices
@@ -568,6 +628,33 @@
 # CONFIG_DVB is not set
 
 #
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -592,17 +679,20 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -611,6 +701,7 @@
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -625,19 +716,20 @@
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
 # CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -647,31 +739,26 @@
 CONFIG_MSDOS_PARTITION=y
 
 #
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
+# Native Language Support
 #
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
+# CONFIG_NLS is not set
 
 #
-# Bluetooth support
+# Library routines
 #
-# CONFIG_BT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
 
 #
-# Library routines
+# Profiling support
 #
-# CONFIG_CRC32 is not set
+# CONFIG_PROFILING is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
 
 #
 # Security options
diff -Nru a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
--- a/arch/ppc/kernel/cpu_setup_6xx.S	2004-07-15 09:16:53 -07:00
+++ b/arch/ppc/kernel/cpu_setup_6xx.S	2004-08-26 02:16:36 -07:00
@@ -218,10 +218,10 @@
 
 	/* All of the bits we have to set.....
 	 */
-	ori	r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK
+	ori	r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC
 BEGIN_FTR_SECTION
-	ori	r11,r11,HID0_BTIC
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_BTIC)
+	xori	r11,r11,HID0_BTIC
+END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
 BEGIN_FTR_SECTION
 	oris	r11,r11,HID0_DPM@h	/* enable dynamic power mgmt */
 END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
diff -Nru a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
--- a/arch/ppc/kernel/cputable.c	2004-08-01 17:30:29 -07:00
+++ b/arch/ppc/kernel/cputable.c	2004-08-24 08:30:14 -07:00
@@ -55,7 +55,7 @@
 #endif
 
 /* We need to mark all pages as being coherent if we're SMP or we
- * have a 754x and an MPC107 host bridge.
+ * have a 74[45]x and an MPC107 host bridge.
  */
 #if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE)
 #define CPU_FTR_COMMON                  CPU_FTR_NEED_COHERENT
diff -Nru a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
--- a/arch/ppc/kernel/head_44x.S	2004-07-28 21:58:35 -07:00
+++ b/arch/ppc/kernel/head_44x.S	2004-08-26 23:30:32 -07:00
@@ -41,16 +41,9 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/offsets.h>
+#include "head_booke.h"
 
-/*
- * Macros
- */
 
-#define SET_IVOR(vector_number, vector_label)		\
-		li	r26,vector_label@l; 		\
-		mtspr	SPRN_IVOR##vector_number,r26;	\
-		sync
-				
 /* As with the other PowerPC ports, it is expected that when code
  * execution begins here, the following registers contain valid, yet
  * optional, information:
@@ -301,234 +294,6 @@
  * Interrupt vectors must be aligned on a 16 byte boundary.
  * We align on a 32 byte cache line boundary for good measure.
  */
-
-#define NORMAL_EXCEPTION_PROLOG						     \
-	mtspr	SPRN_SPRG0,r10;		/* save two registers to work with */\
-	mtspr	SPRN_SPRG1,r11;						     \
-	mtspr	SPRN_SPRG4W,r1;						     \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_SRR1;		/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	beq	1f;							     \
-	mfspr	r1,SPRG3;		/* if from user, start at top of   */\
-	lwz	r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-	addi	r1,r1,THREAD_SIZE;					     \
-1:	subi	r1,r1,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	tophys(r11,r1);							     \
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,GPR10(r11);						     \
-	mfspr	r12,SPRG1;						     \
-	stw	r12,GPR11(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r10,SPRG4R;						     \
-	mfspr	r12,SRR0;						     \
-	stw	r10,GPR1(r11);						     \
-	mfspr	r9,SRR1;						     \
-	stw	r10,0(r11);						     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for critical exceptions.  This is a little different
- * from the normal exception prolog above since a critical exception
- * can potentially occur at any point during normal exception processing.
- * Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors. For Book E
- * processors, we also have a reserved register (SPRG2) that is only used
- * in critical exceptions so we can free up a GPR to use as the base for
- * indirect access to the critical exception save area.  This is necessary
- * since the MMU is always on and the save area is offset from KERNELBASE.
- */
-#define CRITICAL_EXCEPTION_PROLOG					     \
-	mtspr	SPRG2,r8;		/* SPRG2 only used in criticals */   \
-	lis	r8,crit_save@ha;					     \
-	stw	r10,crit_r10@l(r8);					     \
-	stw	r11,crit_r11@l(r8);					     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,crit_sprg0@l(r8);					     \
-	mfspr	r10,SPRG1;						     \
-	stw	r10,crit_sprg1@l(r8);					     \
-	mfspr	r10,SPRG4R;						     \
-	stw	r10,crit_sprg4@l(r8);					     \
-	mfspr	r10,SPRG5R;						     \
-	stw	r10,crit_sprg5@l(r8);					     \
-	mfspr	r10,SPRG7R;						     \
-	stw	r10,crit_sprg7@l(r8);					     \
-	mfspr	r10,SPRN_PID;						     \
-	stw	r10,crit_pid@l(r8);					     \
-	mfspr	r10,SRR0;						     \
-	stw	r10,crit_srr0@l(r8);					     \
-	mfspr	r10,SRR1;						     \
-	stw	r10,crit_srr1@l(r8);					     \
-	mfspr	r8,SPRG2;		/* SPRG2 only used in criticals */   \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_CSRR1;		/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	lis	r11,critical_stack_top@h;				     \
-	ori	r11,r11,critical_stack_top@l;				     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,CSRR0;						     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,CSRR1;						     \
-	stw	r1,0(r11);						     \
-	tovirt(r1,r11);							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for machine check exceptions.  This is similar to
- * the critical exception prolog, except that machine check exceptions
- * have their own save area.  For Book E processors, we also have a
- * reserved register (SPRG6) that is only used in machine check exceptions
- * so we can free up a GPR to use as the base for indirect access to the
- * machine check exception save area.  This is necessary since the MMU
- * is always on and the save area is offset from KERNELBASE.
- */
-#define MCHECK_EXCEPTION_PROLOG					     \
-	mtspr	SPRG6W,r8;		/* SPRG6 used in machine checks */   \
-	lis	r8,mcheck_save@ha;					     \
-	stw	r10,mcheck_r10@l(r8);					     \
-	stw	r11,mcheck_r11@l(r8);					     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,mcheck_sprg0@l(r8);					     \
-	mfspr	r10,SPRG1;						     \
-	stw	r10,mcheck_sprg1@l(r8);					     \
-	mfspr	r10,SPRG4R;						     \
-	stw	r10,mcheck_sprg4@l(r8);					     \
-	mfspr	r10,SPRG5R;						     \
-	stw	r10,mcheck_sprg5@l(r8);					     \
-	mfspr	r10,SPRG7R;						     \
-	stw	r10,mcheck_sprg7@l(r8);					     \
-	mfspr	r10,SPRN_PID;						     \
-	stw	r10,mcheck_pid@l(r8);					     \
-	mfspr	r10,SRR0;						     \
-	stw	r10,mcheck_srr0@l(r8);					     \
-	mfspr	r10,SRR1;						     \
-	stw	r10,mcheck_srr1@l(r8);					     \
-	mfspr	r10,CSRR0;						     \
-	stw	r10,mcheck_csrr0@l(r8);					     \
-	mfspr	r10,CSRR1;						     \
-	stw	r10,mcheck_csrr1@l(r8);					     \
-	mfspr	r8,SPRG6R;		/* SPRG6 used in machine checks */   \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_MCSRR1;	/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	lis	r11,mcheck_stack_top@h;					     \
-	ori	r11,r11,mcheck_stack_top@l;				     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,MCSRR0;						     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,MCSRR1;						     \
-	stw	r1,0(r11);						     \
-	tovirt(r1,r11);							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception vectors.
- */
-#define	START_EXCEPTION(label)						     \
-        .align 5;              						     \
-label:
-
-#define FINISH_EXCEPTION(func)					\
-	bl	transfer_to_handler_full;			\
-	.long	func;						\
-	.long	ret_from_except_full
-
-#define EXCEPTION(n, label, hdlr, xfer)				\
-	START_EXCEPTION(label);					\
-	NORMAL_EXCEPTION_PROLOG;				\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	xfer(n, hdlr)
-
-#define CRITICAL_EXCEPTION(n, label, hdlr)			\
-	START_EXCEPTION(label);					\
-	CRITICAL_EXCEPTION_PROLOG;				\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define MCHECK_EXCEPTION(n, label, hdlr)			\
-	START_EXCEPTION(label);					\
-	MCHECK_EXCEPTION_PROLOG;				\
-	lis	r4,MCSR_MCS@h;					\
-	mtspr	SPRN_MCSR,r4;					\
-	mfspr	r5,SPRN_ESR;					\
-	stw	r5,_ESR(r11);					\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, mcheck_transfer_to_handler,   \
-			  ret_from_mcheck_exc)
-
-#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)	\
-	li	r10,trap;					\
-	stw	r10,TRAP(r11);					\
-	lis	r10,msr@h;					\
-	ori	r10,r10,msr@l;					\
-	copyee(r10, r9);					\
-	bl	tfer;		 				\
-	.long	hdlr;						\
-	.long	ret
-
-#define COPY_EE(d, s)		rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
-			  ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr)	\
-	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
-			  ret_from_except)
 
 interrupt_base:
 	/* Critical Input Interrupt */
diff -Nru a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/kernel/head_booke.h	2004-08-26 23:30:32 -07:00
@@ -0,0 +1,240 @@
+#ifndef __HEAD_BOOKE_H__
+#define __HEAD_BOOKE_H__
+
+/*
+ * Macros used for common Book-e exception handling
+ */
+
+#define SET_IVOR(vector_number, vector_label)		\
+		li	r26,vector_label@l; 		\
+		mtspr	SPRN_IVOR##vector_number,r26;	\
+		sync
+
+#define NORMAL_EXCEPTION_PROLOG						     \
+	mtspr	SPRN_SPRG0,r10;		/* save two registers to work with */\
+	mtspr	SPRN_SPRG1,r11;						     \
+	mtspr	SPRN_SPRG4W,r1;						     \
+	mfcr	r10;			/* save CR in r10 for now	   */\
+	mfspr	r11,SPRN_SRR1;		/* check whether user or kernel    */\
+	andi.	r11,r11,MSR_PR;						     \
+	beq	1f;							     \
+	mfspr	r1,SPRG3;		/* if from user, start at top of   */\
+	lwz	r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
+	addi	r1,r1,THREAD_SIZE;					     \
+1:	subi	r1,r1,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
+	tophys(r11,r1);							     \
+	stw	r10,_CCR(r11);          /* save various registers	   */\
+	stw	r12,GPR12(r11);						     \
+	stw	r9,GPR9(r11);						     \
+	mfspr	r10,SPRG0;						     \
+	stw	r10,GPR10(r11);						     \
+	mfspr	r12,SPRG1;						     \
+	stw	r12,GPR11(r11);						     \
+	mflr	r10;							     \
+	stw	r10,_LINK(r11);						     \
+	mfspr	r10,SPRG4R;						     \
+	mfspr	r12,SRR0;						     \
+	stw	r10,GPR1(r11);						     \
+	mfspr	r9,SRR1;						     \
+	stw	r10,0(r11);						     \
+	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
+	stw	r0,GPR0(r11);						     \
+	SAVE_4GPRS(3, r11);						     \
+	SAVE_2GPRS(7, r11)
+
+/*
+ * Exception prolog for critical exceptions.  This is a little different
+ * from the normal exception prolog above since a critical exception
+ * can potentially occur at any point during normal exception processing.
+ * Thus we cannot use the same SPRG registers as the normal prolog above.
+ * Instead we use a couple of words of memory at low physical addresses.
+ * This is OK since we don't support SMP on these processors. For Book E
+ * processors, we also have a reserved register (SPRG2) that is only used
+ * in critical exceptions so we can free up a GPR to use as the base for
+ * indirect access to the critical exception save area.  This is necessary
+ * since the MMU is always on and the save area is offset from KERNELBASE.
+ */
+#define CRITICAL_EXCEPTION_PROLOG					     \
+	mtspr	SPRG2,r8;		/* SPRG2 only used in criticals */   \
+	lis	r8,crit_save@ha;					     \
+	stw	r10,crit_r10@l(r8);					     \
+	stw	r11,crit_r11@l(r8);					     \
+	mfspr	r10,SPRG0;						     \
+	stw	r10,crit_sprg0@l(r8);					     \
+	mfspr	r10,SPRG1;						     \
+	stw	r10,crit_sprg1@l(r8);					     \
+	mfspr	r10,SPRG4R;						     \
+	stw	r10,crit_sprg4@l(r8);					     \
+	mfspr	r10,SPRG5R;						     \
+	stw	r10,crit_sprg5@l(r8);					     \
+	mfspr	r10,SPRG7R;						     \
+	stw	r10,crit_sprg7@l(r8);					     \
+	mfspr	r10,SPRN_PID;						     \
+	stw	r10,crit_pid@l(r8);					     \
+	mfspr	r10,SRR0;						     \
+	stw	r10,crit_srr0@l(r8);					     \
+	mfspr	r10,SRR1;						     \
+	stw	r10,crit_srr1@l(r8);					     \
+	mfspr	r8,SPRG2;		/* SPRG2 only used in criticals */   \
+	mfcr	r10;			/* save CR in r10 for now	   */\
+	mfspr	r11,SPRN_CSRR1;		/* check whether user or kernel    */\
+	andi.	r11,r11,MSR_PR;						     \
+	lis	r11,critical_stack_top@h;				     \
+	ori	r11,r11,critical_stack_top@l;				     \
+	beq	1f;							     \
+	/* COMING FROM USER MODE */					     \
+	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
+	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+	addi	r11,r11,THREAD_SIZE;					     \
+1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
+	stw	r10,_CCR(r11);          /* save various registers	   */\
+	stw	r12,GPR12(r11);						     \
+	stw	r9,GPR9(r11);						     \
+	mflr	r10;							     \
+	stw	r10,_LINK(r11);						     \
+	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
+	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
+	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
+	stw	r9,_ESR(r11);		/* exception was taken		   */\
+	mfspr	r12,CSRR0;						     \
+	stw	r1,GPR1(r11);						     \
+	mfspr	r9,CSRR1;						     \
+	stw	r1,0(r11);						     \
+	tovirt(r1,r11);							     \
+	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
+	stw	r0,GPR0(r11);						     \
+	SAVE_4GPRS(3, r11);						     \
+	SAVE_2GPRS(7, r11)
+
+/*
+ * Exception prolog for machine check exceptions.  This is similar to
+ * the critical exception prolog, except that machine check exceptions
+ * have their own save area.  For Book E processors, we also have a
+ * reserved register (SPRG6) that is only used in machine check exceptions
+ * so we can free up a GPR to use as the base for indirect access to the
+ * machine check exception save area.  This is necessary since the MMU
+ * is always on and the save area is offset from KERNELBASE.
+ */
+#define MCHECK_EXCEPTION_PROLOG					     \
+	mtspr	SPRG6W,r8;		/* SPRG6 used in machine checks */   \
+	lis	r8,mcheck_save@ha;					     \
+	stw	r10,mcheck_r10@l(r8);					     \
+	stw	r11,mcheck_r11@l(r8);					     \
+	mfspr	r10,SPRG0;						     \
+	stw	r10,mcheck_sprg0@l(r8);					     \
+	mfspr	r10,SPRG1;						     \
+	stw	r10,mcheck_sprg1@l(r8);					     \
+	mfspr	r10,SPRG4R;						     \
+	stw	r10,mcheck_sprg4@l(r8);					     \
+	mfspr	r10,SPRG5R;						     \
+	stw	r10,mcheck_sprg5@l(r8);					     \
+	mfspr	r10,SPRG7R;						     \
+	stw	r10,mcheck_sprg7@l(r8);					     \
+	mfspr	r10,SPRN_PID;						     \
+	stw	r10,mcheck_pid@l(r8);					     \
+	mfspr	r10,SRR0;						     \
+	stw	r10,mcheck_srr0@l(r8);					     \
+	mfspr	r10,SRR1;						     \
+	stw	r10,mcheck_srr1@l(r8);					     \
+	mfspr	r10,CSRR0;						     \
+	stw	r10,mcheck_csrr0@l(r8);					     \
+	mfspr	r10,CSRR1;						     \
+	stw	r10,mcheck_csrr1@l(r8);					     \
+	mfspr	r8,SPRG6R;		/* SPRG6 used in machine checks */   \
+	mfcr	r10;			/* save CR in r10 for now	   */\
+	mfspr	r11,SPRN_MCSRR1;	/* check whether user or kernel    */\
+	andi.	r11,r11,MSR_PR;						     \
+	lis	r11,mcheck_stack_top@h;					     \
+	ori	r11,r11,mcheck_stack_top@l;				     \
+	beq	1f;							     \
+	/* COMING FROM USER MODE */					     \
+	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
+	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+	addi	r11,r11,THREAD_SIZE;					     \
+1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
+	stw	r10,_CCR(r11);          /* save various registers	   */\
+	stw	r12,GPR12(r11);						     \
+	stw	r9,GPR9(r11);						     \
+	mflr	r10;							     \
+	stw	r10,_LINK(r11);						     \
+	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
+	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
+	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
+	stw	r9,_ESR(r11);		/* exception was taken		   */\
+	mfspr	r12,MCSRR0;						     \
+	stw	r1,GPR1(r11);						     \
+	mfspr	r9,MCSRR1;						     \
+	stw	r1,0(r11);						     \
+	tovirt(r1,r11);							     \
+	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
+	stw	r0,GPR0(r11);						     \
+	SAVE_4GPRS(3, r11);						     \
+	SAVE_2GPRS(7, r11)
+
+/*
+ * Exception vectors.
+ */
+#define	START_EXCEPTION(label)						     \
+        .align 5;              						     \
+label:
+
+#define FINISH_EXCEPTION(func)					\
+	bl	transfer_to_handler_full;			\
+	.long	func;						\
+	.long	ret_from_except_full
+
+#define EXCEPTION(n, label, hdlr, xfer)				\
+	START_EXCEPTION(label);					\
+	NORMAL_EXCEPTION_PROLOG;				\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
+	xfer(n, hdlr)
+
+#define CRITICAL_EXCEPTION(n, label, hdlr)			\
+	START_EXCEPTION(label);					\
+	CRITICAL_EXCEPTION_PROLOG;				\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
+	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+			  NOCOPY, transfer_to_handler_full, \
+			  ret_from_except_full)
+
+#define MCHECK_EXCEPTION(n, label, hdlr)			\
+	START_EXCEPTION(label);					\
+	MCHECK_EXCEPTION_PROLOG;				\
+	mfspr	r5,SPRN_ESR;					\
+	stw	r5,_ESR(r11);					\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
+	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+			  NOCOPY, mcheck_transfer_to_handler,   \
+			  ret_from_mcheck_exc)
+
+#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)	\
+	li	r10,trap;					\
+	stw	r10,TRAP(r11);					\
+	lis	r10,msr@h;					\
+	ori	r10,r10,msr@l;					\
+	copyee(r10, r9);					\
+	bl	tfer;		 				\
+	.long	hdlr;						\
+	.long	ret
+
+#define COPY_EE(d, s)		rlwimi d,s,0,16,16
+#define NOCOPY(d, s)
+
+#define EXC_XFER_STD(n, hdlr)		\
+	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
+			  ret_from_except_full)
+
+#define EXC_XFER_LITE(n, hdlr)		\
+	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
+			  ret_from_except)
+
+#define EXC_XFER_EE(n, hdlr)		\
+	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
+			  ret_from_except_full)
+
+#define EXC_XFER_EE_LITE(n, hdlr)	\
+	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
+			  ret_from_except)
+
+
+#endif /* __HEAD_BOOKE_H__ */
diff -Nru a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S
--- a/arch/ppc/kernel/head_e500.S	2004-08-02 09:07:29 -07:00
+++ b/arch/ppc/kernel/head_e500.S	2004-08-26 23:30:32 -07:00
@@ -41,15 +41,7 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/offsets.h>
-
-/*
- * Macros
- */
-
-#define SET_IVOR(vector_number, vector_label)		\
-		li	r26,vector_label@l; 		\
-		mtspr	SPRN_IVOR##vector_number,r26;	\
-		sync
+#include "head_booke.h"
 
 /* As with the other PowerPC ports, it is expected that when code
  * execution begins here, the following registers contain valid, yet
@@ -370,232 +362,6 @@
  * Interrupt vectors must be aligned on a 16 byte boundary.
  * We align on a 32 byte cache line boundary for good measure.
  */
-
-#define NORMAL_EXCEPTION_PROLOG						     \
-	mtspr	SPRN_SPRG0,r10;		/* save two registers to work with */\
-	mtspr	SPRN_SPRG1,r11;						     \
-	mtspr	SPRN_SPRG4W,r1;						     \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_SRR1;		/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	beq	1f;							     \
-	mfspr	r1,SPRG3;		/* if from user, start at top of   */\
-	lwz	r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-	addi	r1,r1,THREAD_SIZE;					     \
-1:	subi	r1,r1,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	tophys(r11,r1);							     \
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,GPR10(r11);						     \
-	mfspr	r12,SPRG1;						     \
-	stw	r12,GPR11(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r10,SPRG4R;						     \
-	mfspr	r12,SRR0;						     \
-	stw	r10,GPR1(r11);						     \
-	mfspr	r9,SRR1;						     \
-	stw	r10,0(r11);						     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for critical exceptions.  This is a little different
- * from the normal exception prolog above since a critical exception
- * can potentially occur at any point during normal exception processing.
- * Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors. For Book E
- * processors, we also have a reserved register (SPRG2) that is only used
- * in critical exceptions so we can free up a GPR to use as the base for
- * indirect access to the critical exception save area.  This is necessary
- * since the MMU is always on and the save area is offset from KERNELBASE.
- */
-#define CRITICAL_EXCEPTION_PROLOG					     \
-	mtspr	SPRG2,r8;		/* SPRG2 only used in criticals */   \
-	lis	r8,crit_save@ha;					     \
-	stw	r10,crit_r10@l(r8);					     \
-	stw	r11,crit_r11@l(r8);					     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,crit_sprg0@l(r8);					     \
-	mfspr	r10,SPRG1;						     \
-	stw	r10,crit_sprg1@l(r8);					     \
-	mfspr	r10,SPRG4R;						     \
-	stw	r10,crit_sprg4@l(r8);					     \
-	mfspr	r10,SPRG5R;						     \
-	stw	r10,crit_sprg5@l(r8);					     \
-	mfspr	r10,SPRG7R;						     \
-	stw	r10,crit_sprg7@l(r8);					     \
-	mfspr	r10,SPRN_PID;						     \
-	stw	r10,crit_pid@l(r8);					     \
-	mfspr	r10,SRR0;						     \
-	stw	r10,crit_srr0@l(r8);					     \
-	mfspr	r10,SRR1;						     \
-	stw	r10,crit_srr1@l(r8);					     \
-	mfspr	r8,SPRG2;		/* SPRG2 only used in criticals */   \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_CSRR1;		/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	lis	r11,critical_stack_top@h;				     \
-	ori	r11,r11,critical_stack_top@l;				     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,CSRR0;						     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,CSRR1;						     \
-	stw	r1,0(r11);						     \
-	tovirt(r1,r11);							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for machine check exceptions.  This is similar to
- * the critical exception prolog, except that machine check exceptions
- * have their own save area.  For Book E processors, we also have a
- * reserved register (SPRG6) that is only used in machine check exceptions
- * so we can free up a GPR to use as the base for indirect access to the
- * machine check exception save area.  This is necessary since the MMU
- * is always on and the save area is offset from KERNELBASE.
- */
-#define MCHECK_EXCEPTION_PROLOG					     \
-	mtspr	SPRG6W,r8;		/* SPRG6 used in machine checks */   \
-	lis	r8,mcheck_save@ha;					     \
-	stw	r10,mcheck_r10@l(r8);					     \
-	stw	r11,mcheck_r11@l(r8);					     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,mcheck_sprg0@l(r8);					     \
-	mfspr	r10,SPRG1;						     \
-	stw	r10,mcheck_sprg1@l(r8);					     \
-	mfspr	r10,SPRG4R;						     \
-	stw	r10,mcheck_sprg4@l(r8);					     \
-	mfspr	r10,SPRG5R;						     \
-	stw	r10,mcheck_sprg5@l(r8);					     \
-	mfspr	r10,SPRG7R;						     \
-	stw	r10,mcheck_sprg7@l(r8);					     \
-	mfspr	r10,SPRN_PID;						     \
-	stw	r10,mcheck_pid@l(r8);					     \
-	mfspr	r10,SRR0;						     \
-	stw	r10,mcheck_srr0@l(r8);					     \
-	mfspr	r10,SRR1;						     \
-	stw	r10,mcheck_srr1@l(r8);					     \
-	mfspr	r10,CSRR0;						     \
-	stw	r10,mcheck_csrr0@l(r8);					     \
-	mfspr	r10,CSRR1;						     \
-	stw	r10,mcheck_csrr1@l(r8);					     \
-	mfspr	r8,SPRG6R;		/* SPRG6 used in machine checks */   \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_MCSRR1;	/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	lis	r11,mcheck_stack_top@h;					     \
-	ori	r11,r11,mcheck_stack_top@l;				     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,MCSRR0;						     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,MCSRR1;						     \
-	stw	r1,0(r11);						     \
-	tovirt(r1,r11);							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception vectors.
- */
-#define	START_EXCEPTION(label)						     \
-        .align 5;              						     \
-label:
-
-#define FINISH_EXCEPTION(func)					\
-	bl	transfer_to_handler_full;			\
-	.long	func;						\
-	.long	ret_from_except_full
-
-#define EXCEPTION(n, label, hdlr, xfer)				\
-	START_EXCEPTION(label);					\
-	NORMAL_EXCEPTION_PROLOG;				\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	xfer(n, hdlr)
-
-#define CRITICAL_EXCEPTION(n, label, hdlr)			\
-	START_EXCEPTION(label);					\
-	CRITICAL_EXCEPTION_PROLOG;				\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define MCHECK_EXCEPTION(n, label, hdlr)			\
-	START_EXCEPTION(label);					\
-	MCHECK_EXCEPTION_PROLOG;				\
-	mfspr	r5,SPRN_ESR;					\
-	stw	r5,_ESR(r11);					\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, mcheck_transfer_to_handler,   \
-			  ret_from_mcheck_exc)
-
-#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)	\
-	li	r10,trap;					\
-	stw	r10,TRAP(r11);					\
-	lis	r10,msr@h;					\
-	ori	r10,r10,msr@l;					\
-	copyee(r10, r9);					\
-	bl	tfer;		 				\
-	.long	hdlr;						\
-	.long	ret
-
-#define COPY_EE(d, s)		rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
-			  ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr)	\
-	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
-			  ret_from_except)
 
 interrupt_base:
 	/* Critical Input Interrupt */
diff -Nru a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
--- a/arch/ppc/kernel/idle.c	2003-09-15 13:59:05 -07:00
+++ b/arch/ppc/kernel/idle.c	2004-08-18 11:19:09 -07:00
@@ -21,6 +21,7 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
+#include <linux/sysctl.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -65,3 +66,36 @@
 			default_idle();
 	return 0;
 }
+
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
+/*
+ * Register the sysctl to set/clear powersave_nap.
+ */
+extern unsigned long powersave_nap;
+
+static ctl_table powersave_nap_ctl_table[]={
+	{
+		.ctl_name	= KERN_PPC_POWERSAVE_NAP,
+		.procname	= "powersave-nap",
+		.data		= &powersave_nap,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{ 0, },
+};
+static ctl_table powersave_nap_sysctl_root[] = {
+	{ 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
+ 	{ 0,},
+};
+
+static int __init
+register_powersave_nap_sysctl(void)
+{
+	register_sysctl_table(powersave_nap_sysctl_root, 0);
+
+	return 0;
+}
+
+__initcall(register_powersave_nap_sysctl);
+#endif
diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
--- a/arch/ppc/kernel/irq.c	2004-08-03 00:19:01 -07:00
+++ b/arch/ppc/kernel/irq.c	2004-08-26 23:30:30 -07:00
@@ -620,32 +620,6 @@
 	return full_count;
 }
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
-					unsigned long count, void *data)
-{
-	int err;
-	int full_count = count;
-	cpumask_t *mask = (cpumask_t *)data;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -673,23 +647,14 @@
 	smp_affinity_entry[irq] = entry;
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", NULL);
-
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	2004-06-22 13:04:07 -07:00
+++ b/arch/ppc/kernel/misc.S	2004-08-17 10:42:55 -07:00
@@ -617,10 +617,9 @@
  * flush_icache_range(unsigned long start, unsigned long stop)
  */
 _GLOBAL(flush_icache_range)
-	mfspr	r5,PVR
-	rlwinm	r5,r5,16,16,31
-	cmpi	0,r5,1
-	beqlr				/* for 601, do nothing */
+BEGIN_FTR_SECTION
+	blr				/* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
 	li	r5,L1_CACHE_LINE_SIZE-1
 	andc	r3,r3,r5
 	subf	r4,r3,r4
@@ -735,10 +734,9 @@
  *	void __flush_dcache_icache(void *page)
  */
 _GLOBAL(__flush_dcache_icache)
-	mfspr	r5,PVR
-	rlwinm	r5,r5,16,16,31
-	cmpi	0,r5,1
-	beqlr					/* for 601, do nothing */
+BEGIN_FTR_SECTION
+	blr					/* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
 	rlwinm	r3,r3,0,0,19			/* Get page base address */
 	li	r4,4096/L1_CACHE_LINE_SIZE	/* Number of lines in a page */
 	mtctr	r4
@@ -764,10 +762,9 @@
  *	void __flush_dcache_icache_phys(unsigned long physaddr)
  */
 _GLOBAL(__flush_dcache_icache_phys)
-	mfspr	r5,PVR
-	rlwinm	r5,r5,16,16,31
-	cmpi	0,r5,1
-	beqlr					/* for 601, do nothing */
+BEGIN_FTR_SECTION
+	blr					/* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
 	mfmsr	r10
 	rlwinm	r0,r10,0,28,26			/* clear DR */
 	mtmsr	r0
diff -Nru a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
--- a/arch/ppc/kernel/pci.c	2004-08-04 04:55:48 -07:00
+++ b/arch/ppc/kernel/pci.c	2004-08-25 23:43:07 -07:00
@@ -144,8 +144,7 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,		PCI_ANY_ID,			pcibios_fixup_resources);
 
-void
-pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 			struct resource *res)
 {
 	unsigned long offset = 0;
@@ -158,6 +157,7 @@
 	region->start = res->start - offset;
 	region->end = res->end - offset;
 }
+EXPORT_SYMBOL(pcibios_resource_to_bus);
 
 /*
  * We need to avoid collisions with `mirrored' VGA ports
@@ -172,8 +172,7 @@
  * but we want to try to avoid allocating at 0x2900-0x2bff
  * which might have be mirrored at 0x0100-0x03ff..
  */
-void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size,
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size,
 		       unsigned long align)
 {
 	struct pci_dev *dev = data;
@@ -193,7 +192,7 @@
 		}
 	}
 }
-
+EXPORT_SYMBOL(pcibios_align_resource);
 
 /*
  *  Handle resources of PCI devices.  If the world were perfect, we could
diff -Nru a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
--- a/arch/ppc/kernel/ppc_htab.c	2004-08-07 23:43:40 -07:00
+++ b/arch/ppc/kernel/ppc_htab.c	2004-08-18 11:19:09 -07:00
@@ -20,6 +20,7 @@
 #include <linux/threads.h>
 #include <linux/smp_lock.h>
 #include <linux/seq_file.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -34,9 +35,6 @@
 static int ppc_htab_show(struct seq_file *m, void *v);
 static ssize_t ppc_htab_write(struct file * file, const char __user * buffer,
 			      size_t count, loff_t *ppos);
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
-		  void __user *buffer, size_t *lenp, loff_t *ppos);
-
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 extern unsigned long _SDR1;
@@ -438,3 +436,32 @@
 	*ppos += *lenp;
 	return 0;
 }
+
+#ifdef CONFIG_SYSCTL
+/*
+ * Register our sysctl.
+ */
+static ctl_table htab_ctl_table[]={
+	{
+		.ctl_name	= KERN_PPC_L2CR,
+		.procname	= "l2cr",
+		.mode		= 0644,
+		.proc_handler	= &proc_dol2crvec,
+	},
+	{ 0, },
+};
+static ctl_table htab_sysctl_root[] = {
+	{ 1, "kernel", NULL, 0, 0755, htab_ctl_table, },
+ 	{ 0,},
+};
+
+static int __init
+register_ppc_htab_sysctl(void)
+{
+	register_sysctl_table(htab_sysctl_root, 0);
+
+	return 0;
+}
+
+__initcall(register_ppc_htab_sysctl);
+#endif
diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
--- a/arch/ppc/kernel/process.c	2004-07-26 14:42:17 -07:00
+++ b/arch/ppc/kernel/process.c	2004-08-27 00:02:36 -07:00
@@ -555,8 +555,7 @@
 	CHECK_FULL_REGS(regs);
 	if (usp == 0)
 		usp = regs->gpr[1];	/* stack pointer for child */
- 	return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
-			parent_tidp, child_tidp);
+ 	return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
 }
 
 int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
@@ -662,7 +661,7 @@
 		++count;
 		sp = *(unsigned long *)sp;
 	}
-#if !CONFIG_KALLSYMS
+#ifndef CONFIG_KALLSYMS
 	if (count > 0)
 		printk("\n");
 #endif
diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
--- a/arch/ppc/kernel/setup.c	2004-08-18 04:38:17 -07:00
+++ b/arch/ppc/kernel/setup.c	2004-08-24 09:02:24 -07:00
@@ -747,6 +747,10 @@
 	if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
 #endif
 
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
 	ppc_md.setup_arch();
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
--- a/arch/ppc/kernel/signal.c	2004-07-26 14:42:38 -07:00
+++ b/arch/ppc/kernel/signal.c	2004-08-25 10:13:41 -07:00
@@ -404,9 +404,7 @@
 	printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
 	       regs, frame, newsp);
 #endif
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
@@ -556,9 +554,7 @@
 	printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
 	       regs, frame, newsp);
 #endif
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -604,7 +600,7 @@
 int do_signal(sigset_t *oldset, struct pt_regs *regs)
 {
 	siginfo_t info;
-	struct k_sigaction *ka;
+	struct k_sigaction ka;
 	unsigned long frame, newsp;
 	int signr, ret;
 
@@ -613,9 +609,7 @@
 
 	newsp = frame = 0;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
-
-	ka = (signr == 0)? NULL: &current->sighand->action[signr-1];
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
 	if (TRAP(regs) == 0x0C00		/* System Call! */
 	    && regs->ccr & 0x10000000		/* error signalled */
@@ -626,7 +620,7 @@
 		if (signr > 0
 		    && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
 			|| (ret == ERESTARTSYS
-			    && !(ka->sa.sa_flags & SA_RESTART)))) {
+			    && !(ka.sa.sa_flags & SA_RESTART)))) {
 			/* make the system call return an EINTR error */
 			regs->result = -EINTR;
 			regs->gpr[3] = EINTR;
@@ -645,7 +639,7 @@
 	if (signr == 0)
 		return 0;		/* no signals delivered */
 
-	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
+	if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
 	    && !on_sig_stack(regs->gpr[1]))
 		newsp = current->sas_ss_sp + current->sas_ss_size;
 	else
@@ -653,17 +647,14 @@
 	newsp &= ~0xfUL;
 
 	/* Whee!  Actually deliver the signal.  */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		handle_rt_signal(signr, ka, &info, oldset, regs, newsp);
+	if (ka.sa.sa_flags & SA_SIGINFO)
+		handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
 	else
-		handle_signal(signr, ka, &info, oldset, regs, newsp);
-
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
+		handle_signal(signr, &ka, &info, oldset, regs, newsp);
 
-	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+	if (!(ka.sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigorsets(&current->blocked,&current->blocked,&ka.sa.sa_mask);
 		sigaddset(&current->blocked, signr);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
diff -Nru a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
--- a/arch/ppc/kernel/smp.c	2004-05-10 04:25:47 -07:00
+++ b/arch/ppc/kernel/smp.c	2004-08-24 02:08:12 -07:00
@@ -364,22 +364,15 @@
 
 int __cpu_up(unsigned int cpu)
 {
-	struct pt_regs regs;
 	struct task_struct *p;
 	char buf[32];
 	int c;
 
 	/* create a process for the processor */
 	/* only regs.msr is actually used, and 0 is OK for it */
-	memset(&regs, 0, sizeof(struct pt_regs));
-	p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+	p = fork_idle(cpu);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-	wake_up_forked_process(p);
-
-	init_idle(p, cpu);
-	unhash_process(p);
-
 	secondary_ti = p->thread_info;
 	p->thread_info->cpu = cpu;
 
diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
--- a/arch/ppc/kernel/time.c	2004-08-23 01:14:33 -07:00
+++ b/arch/ppc/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -108,42 +108,6 @@
 	return delta;
 }
 
-extern char _stext;
-
-static inline void ppc_do_profile (struct pt_regs *regs)
-{
-	unsigned long nip;
-	extern unsigned long prof_cpu_mask;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	nip = instruction_pointer(regs);
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	nip -= (unsigned long) &_stext;
-	nip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds EIP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (nip > prof_len-1)
-		nip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[nip]);
-}
-
 /*
  * timer_interrupt - gets called when the decrementer overflows,
  * with interrupts disabled.
@@ -164,7 +128,7 @@
 	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) <= 0) {
 		jiffy_stamp += tb_ticks_per_jiffy;
 		
-		ppc_do_profile(regs);
+		profile_tick(CPU_PROFILING, regs);
 
 	  	if (smp_processor_id())
 			continue;
diff -Nru a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
--- a/arch/ppc/kernel/vmlinux.lds.S	2004-07-05 03:27:10 -07:00
+++ b/arch/ppc/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -102,9 +102,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init)
diff -Nru a/arch/ppc/math-emu/op-common.h b/arch/ppc/math-emu/op-common.h
--- a/arch/ppc/math-emu/op-common.h	2003-09-12 09:26:52 -07:00
+++ b/arch/ppc/math-emu/op-common.h	2004-08-17 10:40:39 -07:00
@@ -82,7 +82,6 @@
 	if (X##_e <= _FP_WFRACBITS_##fs)			\
 	  {							\
 	    _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);	\
-	    __ret |= _FP_ROUND(wc, X);				\
 	    _FP_FRAC_SLL_##wc(X, 1);				\
 	    if (_FP_FRAC_OVERP_##wc(fs, X))			\
 	      {							\
diff -Nru a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
--- a/arch/ppc/platforms/4xx/ebony.c	2004-05-14 19:00:25 -07:00
+++ b/arch/ppc/platforms/4xx/ebony.c	2004-08-16 09:04:08 -07:00
@@ -361,10 +361,6 @@
 		ROOT_DEV = Root_HDA1;
 #endif
 
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
-#endif
-
 	ebony_early_serial_map();
 
 	ibm4xxPIC_InitSenses = ebony_IRQ_initsenses;
diff -Nru a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
--- a/arch/ppc/platforms/4xx/ocotea.c	2004-05-14 19:00:25 -07:00
+++ b/arch/ppc/platforms/4xx/ocotea.c	2004-08-16 09:04:08 -07:00
@@ -319,10 +319,6 @@
 		ROOT_DEV = Root_HDA1;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	ocotea_early_serial_map(&clocks);
 
 	/* Identify the system */
diff -Nru a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c	2004-08-02 01:00:42 -07:00
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c	2004-08-16 09:04:08 -07:00
@@ -120,10 +120,6 @@
 	mpc85xx_setup_hose();
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 #ifdef CONFIG_SERIAL_8250
 	mpc85xx_early_serial_map();
 #endif
diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2004-08-02 01:00:42 -07:00
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2004-08-27 00:02:36 -07:00
@@ -307,7 +307,7 @@
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
 	/* With the current code we know PCI2 will be bus 2, however this may
 	 * not be guarnteed */
 	if (bus == 2 && PCI_SLOT(devfn) == 0)
@@ -356,10 +356,6 @@
 #ifdef CONFIG_PCI
         /* setup PCI host bridges */
         mpc85xx_setup_hose();
-#endif
-
-#ifdef CONFIG_DUMMY_CONSOLE
-        conswitchp = &dummy_con;
 #endif
 
 #ifdef CONFIG_SERIAL_8250
diff -Nru a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
--- a/arch/ppc/platforms/85xx/sbc8560.c	2004-08-02 01:00:42 -07:00
+++ b/arch/ppc/platforms/85xx/sbc8560.c	2004-08-16 09:04:08 -07:00
@@ -144,9 +144,6 @@
 	/* setup PCI host bridges */
 	mpc85xx_setup_hose();
 #endif
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
 #ifdef CONFIG_SERIAL_8250
 	sbc8560_early_serial_map();
 #endif
diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
--- a/arch/ppc/platforms/Makefile	2004-08-05 11:11:06 -07:00
+++ b/arch/ppc/platforms/Makefile	2004-08-13 16:33:53 -07:00
@@ -21,23 +21,21 @@
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
 obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
 obj-$(CONFIG_ADIR)		+= adir_setup.o adir_pic.o adir_pci.o
-obj-$(CONFIG_EST8260)		+= est8260_setup.o
-obj-$(CONFIG_PQ2ADS)		+= pq2ads_setup.o
+obj-$(CONFIG_PQ2ADS)		+= pq2ads.o
 obj-$(CONFIG_TQM8260)		+= tqm8260_setup.o
 obj-$(CONFIG_EV64260)		+= ev64260_setup.o
 obj-$(CONFIG_GEMINI)		+= gemini_pci.o gemini_setup.o gemini_prom.o
 obj-$(CONFIG_K2)		+= k2.o
-obj-$(CONFIG_LOPEC)		+= lopec_setup.o lopec_pci.o
+obj-$(CONFIG_LOPEC)		+= lopec.o
 obj-$(CONFIG_MCPN765)		+= mcpn765.o
 obj-$(CONFIG_MENF1)		+= menf1_setup.o menf1_pci.o
-obj-$(CONFIG_MVME5100)		+= mvme5100_setup.o mvme5100_pci.o
+obj-$(CONFIG_MVME5100)		+= mvme5100.o
 obj-$(CONFIG_PAL4)		+= pal4_setup.o pal4_pci.o
 obj-$(CONFIG_PCORE)		+= pcore.o
 obj-$(CONFIG_POWERPMC250)	+= powerpmc250.o
 obj-$(CONFIG_PPLUS)		+= pplus.o
 obj-$(CONFIG_PRPMC750)		+= prpmc750.o
 obj-$(CONFIG_PRPMC800)		+= prpmc800.o
-obj-$(CONFIG_RPX8260)		+= rpx8260.o
 obj-$(CONFIG_SANDPOINT)		+= sandpoint.o
 obj-$(CONFIG_SBC82xx)		+= sbc82xx.o
 obj-$(CONFIG_SPRUCE)		+= spruce.o
diff -Nru a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
--- a/arch/ppc/platforms/chrp_setup.c	2004-04-28 00:21:32 -07:00
+++ b/arch/ppc/platforms/chrp_setup.c	2004-08-16 09:04:08 -07:00
@@ -250,13 +250,6 @@
 	 */
 	sio_init();
 
-	/*
-	 *  Setup the console operations
-	 */
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	/* Get the event scan rate for the rtas so we know how
 	 * often it expects a heartbeat. -- Cort
 	 */
diff -Nru a/arch/ppc/platforms/est8260.h b/arch/ppc/platforms/est8260.h
--- a/arch/ppc/platforms/est8260.h	2004-06-16 10:56:13 -07:00
+++ b/arch/ppc/platforms/est8260.h	2004-08-13 14:03:33 -07:00
@@ -10,6 +10,9 @@
 
 #define BOOTROM_RESTART_ADDR	((uint)0xff000104)
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"EST Corporation"
+#define CPUINFO_MACHINE		"SBC8260 PowerPC"
 
 /* A Board Information structure that is given to a program when
  * prom starts it up.
diff -Nru a/arch/ppc/platforms/est8260_setup.c b/arch/ppc/platforms/est8260_setup.c
--- a/arch/ppc/platforms/est8260_setup.c	2003-09-12 09:26:53 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,65 +0,0 @@
-/*
- * arch/ppc/platforms/est8260_setup.c
- *
- * EST8260 platform support
- *
- * Author: Allen Curtis <acurtis@onz.com>
- * Derived from: m8260_setup.c by Dan Malek, MVista
- *
- * Copyright 2002 Ones and Zeros, Inc.
- *
- * 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 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/seq_file.h>
-
-#include <asm/mpc8260.h>
-#include <asm/machdep.h>
-
-static void (*callback_setup_arch)(void);
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void m8260_init(unsigned long r3, unsigned long r4,
-	unsigned long r5, unsigned long r6, unsigned long r7);
-
-static int
-est8260_show_cpuinfo(struct seq_file *m)
-{
-	bd_t	*binfo = (bd_t *)__res;
-
-	seq_printf(m, "vendor\t\t: EST Corporation\n"
-		      "machine\t\t: SBC8260 PowerPC\n"
-		      "\n"
-		      "mem size\t\t: 0x%08x\n"
-		      "console baud\t\t: %d\n"
-		      "\n",
-		      binfo->bi_memsize,
-		      binfo->bi_baudrate);
-	return 0;
-}
-
-static void __init
-est8260_setup_arch(void)
-{
-	printk("EST SBC8260 Port\n");
-	callback_setup_arch();
-}
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
-{
-	/* Generic 8260 platform initialization */
-	m8260_init(r3, r4, r5, r6, r7);
-
-	/* Anything special for this platform */
-	ppc_md.show_cpuinfo	= est8260_show_cpuinfo;
-
-	callback_setup_arch	= ppc_md.setup_arch;
-	ppc_md.setup_arch	= est8260_setup_arch;
-}
diff -Nru a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c
--- a/arch/ppc/platforms/k2.c	2004-04-28 08:14:54 -07:00
+++ b/arch/ppc/platforms/k2.c	2004-08-16 09:04:08 -07:00
@@ -464,10 +464,6 @@
 		ROOT_DEV = Root_HDC1;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	/* Identify the system */
 	printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ "
 			"%d Mhz\n", k2_get_cpu_speed() / 1000000);
diff -Nru a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/lopec.c	2004-08-24 08:31:19 -07:00
@@ -0,0 +1,410 @@
+/*
+ * arch/ppc/platforms/lopec.c
+ *
+ * Setup routines for the Motorola LoPEC.
+ *
+ * Author: Dan Cox
+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pci_ids.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/root_dev.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/io.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/hw_irq.h>
+#include <asm/prep_nvram.h>
+#include <asm/kgdb.h>
+
+/*
+ * Define all of the IRQ senses and polarities.  Taken from the
+ * LoPEC Programmer's Reference Guide.
+ */
+static u_char lopec_openpic_initsenses[16] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 4 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 5 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 6 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 7 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 8 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 9 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 10 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 11 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 12 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 13 */
+	(IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),	/* IRQ 14 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE)	/* IRQ 15 */
+};
+
+static inline int __init
+lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	int irq;
+	static char pci_irq_table[][4] = {
+		{16, 0, 0, 0}, /* ID 11 - Winbond */
+		{22, 0, 0, 0}, /* ID 12 - SCSI */
+		{0, 0, 0, 0}, /* ID 13 - nothing */
+		{17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */
+		{27, 0, 0, 0}, /* ID 15 - USB */
+		{23, 0, 0, 0}, /* ID 16 - PMC slot 1 */
+		{24, 0, 0, 0}, /* ID 17 - PMC slot 2 */
+		{25, 0, 0, 0}, /* ID 18 - PCI slot */
+		{0, 0, 0, 0}, /* ID 19 - nothing */
+		{0, 0, 0, 0}, /* ID 20 - nothing */
+		{0, 0, 0, 0}, /* ID 21 - nothing */
+		{0, 0, 0, 0}, /* ID 22 - nothing */
+		{0, 0, 0, 0}, /* ID 23 - nothing */
+		{0, 0, 0, 0}, /* ID 24 - PMC slot 1b */
+		{0, 0, 0, 0}, /* ID 25 - nothing */
+		{0, 0, 0, 0}  /* ID 26 - PMC Slot 2b */
+	};
+	const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4;
+
+	irq = PCI_IRQ_TABLE_LOOKUP;
+	if (!irq)
+		return 0;
+
+	return irq;
+}
+
+static void __init
+lopec_setup_winbond_83553(struct pci_controller *hose)
+{
+	int devfn;
+
+	devfn = PCI_DEVFN(11,0);
+
+	/* IDE interrupt routing (primary 14, secondary 15) */
+	early_write_config_byte(hose, 0, devfn, 0x43, 0xef);
+	/* PCI interrupt routing */
+	early_write_config_word(hose, 0, devfn, 0x44, 0x0000);
+
+	/* ISA-PCI address decoder */
+	early_write_config_byte(hose, 0, devfn, 0x48, 0xf0);
+
+	/* RTC, kb, not used in PPC */
+	early_write_config_byte(hose, 0, devfn, 0x4d, 0x00);
+	early_write_config_byte(hose, 0, devfn, 0x4e, 0x04);
+	devfn = PCI_DEVFN(11, 1);
+	early_write_config_byte(hose, 0, devfn, 0x09, 0x8f);
+	early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011);
+}
+
+static void __init
+lopec_find_bridges(void)
+{
+	struct pci_controller *hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	if (mpc10x_bridge_init(hose, MPC10X_MEM_MAP_B, MPC10X_MEM_MAP_B,
+				MPC10X_MAPB_EUMB_BASE) == 0) {
+
+		hose->mem_resources[0].end = 0xffffffff;
+		lopec_setup_winbond_83553(hose);
+		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+		ppc_md.pci_swizzle = common_swizzle;
+		ppc_md.pci_map_irq = lopec_map_irq;
+	}
+}
+
+static int
+lopec_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "machine\t\t: Motorola LoPEC\n");
+	return 0;
+}
+
+static u32
+lopec_irq_canonicalize(u32 irq)
+{
+	if (irq == 2)
+		return 9;
+	else
+		return irq;
+}
+
+static void
+lopec_restart(char *cmd)
+{
+#define LOPEC_SYSSTAT1 0xffe00000
+	/* force a hard reset, if possible */
+	unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1);
+	reg |= 0x80;
+	*((unsigned char *) LOPEC_SYSSTAT1) = reg;
+
+	local_irq_disable();
+	while(1);
+#undef LOPEC_SYSSTAT1
+}
+
+static void
+lopec_halt(void)
+{
+	local_irq_disable();
+	while(1);
+}
+
+static void
+lopec_power_off(void)
+{
+	lopec_halt();
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+int lopec_ide_ports_known = 0;
+static unsigned long lopec_ide_regbase[MAX_HWIFS];
+static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long lopec_idedma_regbase;
+
+static void
+lopec_ide_probe(void)
+{
+	struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
+					      PCI_DEVICE_ID_WINBOND_82C105,
+					      NULL);
+	lopec_ide_ports_known = 1;
+
+	if (dev) {
+		lopec_ide_regbase[0] = dev->resource[0].start;
+		lopec_ide_regbase[1] = dev->resource[2].start;
+		lopec_ide_ctl_regbase[0] = dev->resource[1].start;
+		lopec_ide_ctl_regbase[1] = dev->resource[3].start;
+		lopec_idedma_regbase = dev->resource[4].start;
+	}
+}
+
+static int
+lopec_ide_default_irq(unsigned long base)
+{
+	if (lopec_ide_ports_known == 0)
+		lopec_ide_probe();
+
+	if (base == lopec_ide_regbase[0])
+		return 14;
+	else if (base == lopec_ide_regbase[1])
+		return 15;
+	else
+		return 0;
+}
+
+static unsigned long
+lopec_ide_default_io_base(int index)
+{
+	if (lopec_ide_ports_known == 0)
+		lopec_ide_probe();
+	return lopec_ide_regbase[index];
+}
+
+static void __init
+lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data,
+			  unsigned long ctl, int *irq)
+{
+	unsigned long reg = data;
+	uint alt_status_base;
+	int i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+		hw->io_ports[i] = reg++;
+
+	if (data == lopec_ide_regbase[0]) {
+		alt_status_base = lopec_ide_ctl_regbase[0] + 2;
+		hw->irq = 14;
+	} else if (data == lopec_ide_regbase[1]) {
+		alt_status_base = lopec_ide_ctl_regbase[1] + 2;
+		hw->irq = 15;
+	} else {
+		alt_status_base = 0;
+		hw->irq = 0;
+	}
+
+	if (ctl)
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
+	else
+		hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+
+	if (irq != NULL)
+		*irq = hw->irq;
+
+}
+#endif /* BLK_DEV_IDE */
+
+static void __init
+lopec_init_IRQ(void)
+{
+	int i;
+
+	/*
+	 * Provide the open_pic code with the correct table of interrupts.
+	 */
+	OpenPIC_InitSenses = lopec_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses);
+
+	mpc10x_set_openpic();
+
+	/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			&i8259_irq);
+
+	/* Map i8259 interrupts */
+	for(i = 0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	/*
+	 * The EPIC allows for a read in the range of 0xFEF00000 ->
+	 * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+	 */
+	i8259_init(0xfef00000);
+}
+
+static int __init
+lopec_request_io(void)
+{
+	outb(0x00, 0x4d0);
+	outb(0xc0, 0x4d1);
+
+	request_region(0x00, 0x20, "dma1");
+	request_region(0x20, 0x20, "pic1");
+	request_region(0x40, 0x20, "timer");
+	request_region(0x80, 0x10, "dma page reg");
+	request_region(0xa0, 0x20, "pic2");
+	request_region(0xc0, 0x20, "dma2");
+
+	return 0;
+}
+
+device_initcall(lopec_request_io);
+
+static void __init
+lopec_map_io(void)
+{
+	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+	io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO);
+}
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+lopec_set_bat(void)
+{
+	mb();
+	mtspr(DBAT1U, 0xf8000ffe);
+	mtspr(DBAT1L, 0xf800002a);
+	mb();
+}
+
+TODC_ALLOC();
+
+static void __init
+lopec_setup_arch(void)
+{
+
+	TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+		  ioremap(0xffe80000, 0x8000), 8);
+
+	loops_per_jiffy = 100000000/HZ;
+
+	lopec_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#elif defined(CONFIG_ROOT_NFS)
+        	ROOT_DEV = Root_NFS;
+#elif defined(CONFIG_BLK_DEV_IDEDISK)
+	        ROOT_DEV = Root_HDA1;
+#else
+        	ROOT_DEV = Root_SDA1;
+#endif
+
+#ifdef CONFIG_PPCBUG_NVRAM
+	/* Read in NVRAM data */
+	init_prep_nvram();
+
+	/* if no bootargs, look in NVRAM */
+	if ( cmd_line[0] == '\0' ) {
+		char *bootargs;
+		 bootargs = prep_nvram_get_var("bootargs");
+		 if (bootargs != NULL) {
+			 strcpy(cmd_line, bootargs);
+			 /* again.. */
+			 strcpy(saved_command_line, cmd_line);
+		}
+	}
+#endif
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+	lopec_set_bat();
+
+	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch = lopec_setup_arch;
+	ppc_md.show_cpuinfo = lopec_show_cpuinfo;
+	ppc_md.irq_canonicalize = lopec_irq_canonicalize;
+	ppc_md.init_IRQ = lopec_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = lopec_restart;
+	ppc_md.power_off = lopec_power_off;
+	ppc_md.halt = lopec_halt;
+
+	ppc_md.setup_io_mappings = lopec_map_io;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	ppc_ide_md.default_irq = lopec_ide_default_irq;
+	ppc_ide_md.default_io_base = lopec_ide_default_io_base;
+	ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif
+}
diff -Nru a/arch/ppc/platforms/lopec.h b/arch/ppc/platforms/lopec.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/lopec.h	2004-08-12 12:27:25 -07:00
@@ -0,0 +1,39 @@
+/*
+ * include/asm-ppc/lopec_serial.h
+ *
+ * Definitions for Motorola LoPEC board.
+ *
+ * Author: Dan Cox
+ *         danc@mvista.com (or, alternately, source@mvista.com)
+ *
+ * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __H_LOPEC_SERIAL
+#define __H_LOPEC_SERIAL
+
+#define RS_TABLE_SIZE 3
+
+#define BASE_BAUD (1843200 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+#define SERIAL_PORT_DFNS \
+         { 0, BASE_BAUD, 0xffe10000, 29, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe10000, \
+           io_type: SERIAL_IO_MEM }, \
+         { 0, BASE_BAUD, 0xffe11000, 20, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe11000, \
+           io_type: SERIAL_IO_MEM }, \
+         { 0, BASE_BAUD, 0xffe12000, 21, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe12000, \
+           io_type: SERIAL_IO_MEM }
+
+#endif
diff -Nru a/arch/ppc/platforms/lopec_pci.c b/arch/ppc/platforms/lopec_pci.c
--- a/arch/ppc/platforms/lopec_pci.c	2003-09-12 09:26:53 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,99 +0,0 @@
-/*
- * arch/ppc/platforms/lopec_pci.c
- *
- * PCI setup routines for the Motorola LoPEC.
- *
- * Author: Dan Cox
- *         danc@mvista.com (or, alternately, source@mvista.com)
- *
- * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/mpc10x.h>
-
-static inline int __init
-lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	int irq;
-	static char pci_irq_table[][4] = {
-		{16, 0, 0, 0}, /* ID 11 - Winbond */
-		{22, 0, 0, 0}, /* ID 12 - SCSI */
-		{0, 0, 0, 0}, /* ID 13 - nothing */
-		{17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */
-		{27, 0, 0, 0}, /* ID 15 - USB */
-		{23, 0, 0, 0}, /* ID 16 - PMC slot 1 */
-		{24, 0, 0, 0}, /* ID 17 - PMC slot 2 */
-		{25, 0, 0, 0}, /* ID 18 - PCI slot */
-		{0, 0, 0, 0}, /* ID 19 - nothing */
-		{0, 0, 0, 0}, /* ID 20 - nothing */
-		{0, 0, 0, 0}, /* ID 21 - nothing */
-		{0, 0, 0, 0}, /* ID 22 - nothing */
-		{0, 0, 0, 0}, /* ID 23 - nothing */
-		{0, 0, 0, 0}, /* ID 24 - PMC slot 1b */
-		{0, 0, 0, 0}, /* ID 25 - nothing */
-		{0, 0, 0, 0}  /* ID 26 - PMC Slot 2b */
-	};
-	const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4;
-
-	irq = PCI_IRQ_TABLE_LOOKUP;
-	if (!irq)
-		return 0;
-
-	return irq;
-}
-
-void __init
-lopec_setup_winbond_83553(struct pci_controller *hose)
-{
-	int devfn;
-
-	devfn = PCI_DEVFN(11,0);
-
-	/* IDE interrupt routing (primary 14, secondary 15) */
-	early_write_config_byte(hose, 0, devfn, 0x43, 0xef);
-	/* PCI interrupt routing */
-	early_write_config_word(hose, 0, devfn, 0x44, 0x0000);
-
-	/* ISA-PCI address decoder */
-	early_write_config_byte(hose, 0, devfn, 0x48, 0xf0);
-
-	/* RTC, kb, not used in PPC */
-	early_write_config_byte(hose, 0, devfn, 0x4d, 0x00);
-	early_write_config_byte(hose, 0, devfn, 0x4e, 0x04);
-	devfn = PCI_DEVFN(11, 1);
-	early_write_config_byte(hose, 0, devfn, 0x09, 0x8f);
-	early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011);
-}
-
-void __init
-lopec_find_bridges(void)
-{
-	struct pci_controller *hose;
-
-	hose = pcibios_alloc_controller();
-	if (!hose)
-		return;
-
-	hose->first_busno = 0;
-	hose->last_busno = 0xff;
-
-	if (mpc10x_bridge_init(hose,
-			       MPC10X_MEM_MAP_B,
-			       MPC10X_MEM_MAP_B,
-			       MPC10X_MAPB_EUMB_BASE) == 0) {
-
-		hose->mem_resources[0].end = 0xffffffff;
-		lopec_setup_winbond_83553(hose);
-		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-		ppc_md.pci_swizzle = common_swizzle;
-		ppc_md.pci_map_irq = lopec_map_irq;
-	}
-}
diff -Nru a/arch/ppc/platforms/lopec_serial.h b/arch/ppc/platforms/lopec_serial.h
--- a/arch/ppc/platforms/lopec_serial.h	2003-09-12 09:26:53 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,39 +0,0 @@
-/*
- * include/asm-ppc/lopec_serial.h
- *
- * Definitions for Motorola LoPEC board.
- *
- * Author: Dan Cox
- *         danc@mvista.com (or, alternately, source@mvista.com)
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __H_LOPEC_SERIAL
-#define __H_LOPEC_SERIAL
-
-#define RS_TABLE_SIZE 3
-
-#define BASE_BAUD (1843200 / 16)
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-#define SERIAL_PORT_DFNS \
-         { 0, BASE_BAUD, 0xffe10000, 29, STD_COM_FLAGS, \
-           iomem_base: (u8 *) 0xffe10000, \
-           io_type: SERIAL_IO_MEM }, \
-         { 0, BASE_BAUD, 0xffe11000, 20, STD_COM_FLAGS, \
-           iomem_base: (u8 *) 0xffe11000, \
-           io_type: SERIAL_IO_MEM }, \
-         { 0, BASE_BAUD, 0xffe12000, 21, STD_COM_FLAGS, \
-           iomem_base: (u8 *) 0xffe12000, \
-           io_type: SERIAL_IO_MEM }
-
-#endif
diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c
--- a/arch/ppc/platforms/lopec_setup.c	2004-07-01 22:23:46 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,378 +0,0 @@
-/*
- * arch/ppc/platforms/lopec_setup.c
- *
- * Setup routines for the Motorola LoPEC.
- *
- * Author: Dan Cox
- *         danc@mvista.com
- *
- * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/pci_ids.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/root_dev.h>
-
-#include <asm/io.h>
-#include <asm/open_pic.h>
-#include <asm/i8259.h>
-#include <asm/todc.h>
-#include <asm/bootinfo.h>
-#include <asm/mpc10x.h>
-#include <asm/hw_irq.h>
-#include <asm/prep_nvram.h>
-
-extern void lopec_find_bridges(void);
-
-/*
- * Define all of the IRQ senses and polarities.  Taken from the
- * LoPEC Programmer's Reference Guide.
- */
-static u_char lopec_openpic_initsenses[16] __initdata = {
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 0 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 3 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 4 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 5 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 6 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 7 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 8 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 9 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 10 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 11 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 12 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 13 */
-	(IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),	/* IRQ 14 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE)	/* IRQ 15 */
-};
-
-static int
-lopec_show_cpuinfo(struct seq_file *m)
-{
-	seq_printf(m, "machine\t\t: Motorola LoPEC\n");
-	return 0;
-}
-
-static u32
-lopec_irq_canonicalize(u32 irq)
-{
-	if (irq == 2)
-		return 9;
-	else
-		return irq;
-}
-
-static void
-lopec_restart(char *cmd)
-{
-#define LOPEC_SYSSTAT1 0xffe00000
-	/* force a hard reset, if possible */
-	unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1);
-	reg |= 0x80;
-	*((unsigned char *) LOPEC_SYSSTAT1) = reg;
-
-	local_irq_disable();
-	while(1);
-#undef LOPEC_SYSSTAT1
-}
-
-static void
-lopec_halt(void)
-{
-	local_irq_disable();
-	while(1);
-}
-
-static void
-lopec_power_off(void)
-{
-	lopec_halt();
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-int lopec_ide_ports_known = 0;
-static unsigned long lopec_ide_regbase[MAX_HWIFS];
-static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS];
-static unsigned long lopec_idedma_regbase;
-
-static void
-lopec_ide_probe(void)
-{
-	struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
-					      PCI_DEVICE_ID_WINBOND_82C105,
-					      NULL);
-	lopec_ide_ports_known = 1;
-
-	if (dev) {
-		lopec_ide_regbase[0] = dev->resource[0].start;
-		lopec_ide_regbase[1] = dev->resource[2].start;
-		lopec_ide_ctl_regbase[0] = dev->resource[1].start;
-		lopec_ide_ctl_regbase[1] = dev->resource[3].start;
-		lopec_idedma_regbase = dev->resource[4].start;
-	}
-}
-
-static int
-lopec_ide_default_irq(unsigned long base)
-{
-	if (lopec_ide_ports_known == 0)
-		lopec_ide_probe();
-
-	if (base == lopec_ide_regbase[0])
-		return 14;
-	else if (base == lopec_ide_regbase[1])
-		return 15;
-	else
-		return 0;
-}
-
-static unsigned long
-lopec_ide_default_io_base(int index)
-{
-	if (lopec_ide_ports_known == 0)
-		lopec_ide_probe();
-	return lopec_ide_regbase[index];
-}
-
-static void __init
-lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data,
-			  unsigned long ctl, int *irq)
-{
-	unsigned long reg = data;
-	uint alt_status_base;
-	int i;
-
-	for(i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-		hw->io_ports[i] = reg++;
-
-	if (data == lopec_ide_regbase[0]) {
-		alt_status_base = lopec_ide_ctl_regbase[0] + 2;
-		hw->irq = 14;
-	}
-	else if (data == lopec_ide_regbase[1]) {
-		alt_status_base = lopec_ide_ctl_regbase[1] + 2;
-		hw->irq = 15;
-	}
-	else {
-		alt_status_base = 0;
-		hw->irq = 0;
-	}
-
-	if (ctl)
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
-	else
-		hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
-
-	if (irq != NULL)
-		*irq = hw->irq;
-
-}
-#endif /* BLK_DEV_IDE */
-
-static void __init
-lopec_init_IRQ(void)
-{
-	int i;
-
-	/*
-	 * Provide the open_pic code with the correct table of interrupts.
-	 */
-	OpenPIC_InitSenses = lopec_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses);
-
-	mpc10x_set_openpic();
-
-	/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
-	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-			&i8259_irq);
-
-	/* Map i8259 interrupts */
-	for(i = 0; i < NUM_8259_INTERRUPTS; i++)
-		irq_desc[i].handler = &i8259_pic;
-
-	/*
-	 * The EPIC allows for a read in the range of 0xFEF00000 ->
-	 * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
-	 */
-	i8259_init(0xfef00000);
-}
-
-static int __init
-lopec_request_io(void)
-{
-	outb(0x00, 0x4d0);
-	outb(0xc0, 0x4d1);
-
-	request_region(0x00, 0x20, "dma1");
-	request_region(0x20, 0x20, "pic1");
-	request_region(0x40, 0x20, "timer");
-	request_region(0x80, 0x10, "dma page reg");
-	request_region(0xa0, 0x20, "pic2");
-	request_region(0xc0, 0x20, "dma2");
-
-	return 0;
-}
-
-device_initcall(lopec_request_io);
-
-static void __init
-lopec_map_io(void)
-{
-	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
-	io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO);
-}
-
-static void __init
-lopec_set_bat(void)
-{
-	unsigned long batu, batl;
-
-	__asm__ __volatile__(
-		"lis %0,0xf800\n \
-                 ori %1,%0,0x002a\n \
-                 ori %0,%0,0x0ffe\n \
-                 mtspr 0x21e,%0\n \
-                 mtspr 0x21f,%1\n \
-                 isync\n \
-                 sync "
-		: "=r" (batu), "=r" (batl));
-}
-
-#ifdef  CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
-	SERIAL_PORT_DFNS	/* Defined in <asm/serial.h> */
-};
-
-volatile unsigned char *com_port;
-volatile unsigned char *com_port_lsr;
-
-static void
-serial_writechar(char c)
-{
-	while ((*com_port_lsr & UART_LSR_THRE) == 0)
-		;
-	*com_port = c;
-}
-
-void
-lopec_progress(char *s, unsigned short hex)
-{
-	volatile char c;
-
-	com_port = (volatile unsigned char *) rs_table[0].port;
-	com_port_lsr = com_port + UART_LSR;
-
-	while ((c = *s++) != 0)
-		serial_writechar(c);
-
-	/* Most messages don't have a newline in them */
-	serial_writechar('\n');
-	serial_writechar('\r');
-}
-#endif	/* CONFIG_SERIAL_TEXT_DEBUG */
-
-TODC_ALLOC();
-
-static void __init
-lopec_setup_arch(void)
-{
-
-	TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
-		  ioremap(0xffe80000, 0x8000), 8);
-
-	loops_per_jiffy = 100000000/HZ;
-
-	lopec_find_bridges();
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#elif defined(CONFIG_ROOT_NFS)
-        	ROOT_DEV = Root_NFS;
-#elif defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-	        ROOT_DEV = Root_HDA1;
-#else
-        	ROOT_DEV = Root_SDA1;
-#endif
-
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
-#endif
-#ifdef CONFIG_PPCBUG_NVRAM
-	/* Read in NVRAM data */
-	init_prep_nvram();
-
-	/* if no bootargs, look in NVRAM */
-	if ( cmd_line[0] == '\0' ) {
-		char *bootargs;
-		 bootargs = prep_nvram_get_var("bootargs");
-		 if (bootargs != NULL) {
-			 strcpy(cmd_line, bootargs);
-			 /* again.. */
-			 strcpy(saved_command_line, cmd_line);
-		}
-	}
-#endif
-}
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
-{
-	parse_bootinfo(find_bootinfo());
-	lopec_set_bat();
-
-	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
-	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
-	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
-	ISA_DMA_THRESHOLD = 0x00ffffff;
-	DMA_MODE_READ = 0x44;
-	DMA_MODE_WRITE = 0x48;
-
-	ppc_md.setup_arch = lopec_setup_arch;
-	ppc_md.show_cpuinfo = lopec_show_cpuinfo;
-	ppc_md.irq_canonicalize = lopec_irq_canonicalize;
-	ppc_md.init_IRQ = lopec_init_IRQ;
-	ppc_md.get_irq = openpic_get_irq;
-
-	ppc_md.restart = lopec_restart;
-	ppc_md.power_off = lopec_power_off;
-	ppc_md.halt = lopec_halt;
-
-	ppc_md.setup_io_mappings = lopec_map_io;
-
-	ppc_md.time_init = todc_time_init;
-	ppc_md.set_rtc_time = todc_set_rtc_time;
-	ppc_md.get_rtc_time = todc_get_rtc_time;
-	ppc_md.calibrate_decr = todc_calibrate_decr;
-
-	ppc_md.nvram_read_val = todc_direct_read_val;
-	ppc_md.nvram_write_val = todc_direct_write_val;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-	ppc_ide_md.default_irq = lopec_ide_default_irq;
-	ppc_ide_md.default_io_base = lopec_ide_default_io_base;
-	ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
-#endif
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-	ppc_md.progress = lopec_progress;
-#endif
-}
diff -Nru a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c
--- a/arch/ppc/platforms/mcpn765.c	2004-04-28 00:21:32 -07:00
+++ b/arch/ppc/platforms/mcpn765.c	2004-08-24 08:31:19 -07:00
@@ -58,8 +58,6 @@
 #include <asm/kgdb.h>
 
 #include "mcpn765.h"
-#include "mcpn765_serial.h"
-
 
 static u_char mcpn765_openpic_initsenses[] __initdata = {
 	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */
@@ -322,10 +320,6 @@
 		ROOT_DEV = Root_NFS;
 #else
 		ROOT_DEV = Root_SDA2;
-#endif
-
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
 #endif
 
 	if ( ppc_md.progress )
diff -Nru a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h
--- a/arch/ppc/platforms/mcpn765.h	2003-09-12 09:26:53 -07:00
+++ b/arch/ppc/platforms/mcpn765.h	2004-08-12 12:15:58 -07:00
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer
  *         mgreer@mvista.com
  *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
  * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
@@ -25,6 +25,7 @@
 
 #ifndef __PPC_PLATFORMS_MCPN765_H
 #define __PPC_PLATFORMS_MCPN765_H
+#include <linux/config.h>
 
 /* PCI Memory space mapping info */
 #define	MCPN765_PCI_MEM_SIZE		0x40000000U
@@ -65,13 +66,56 @@
 #define	MCPN765_BOARD_EXT_FEATURE_REG	0xfef880f0U
 #define	MCPN765_BOARD_LAST_RESET_REG	0xfef880f8U
 
-/* UART base addresses are defined in <asm-ppc/platforms/mcpn765_serial.h> */
+/* Defines for UART */
+
+/* Define the UART base addresses */
+#define	MCPN765_SERIAL_1		0xfef88000
+#define	MCPN765_SERIAL_2		0xfef88200
+#define	MCPN765_SERIAL_3		0xfef88400
+#define	MCPN765_SERIAL_4		0xfef88600
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  4
+#endif
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD	( 1843200 / 16 )
+#define UART_CLK	1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+/* All UART IRQ's are wire-OR'd to IRQ 17 */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_1,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_2,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_3,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_4,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
 
 /* Define the NVRAM/RTC address strobe & data registers */
 #define MCPN765_PHYS_NVRAM_AS0          0xfef880c8U
 #define MCPN765_PHYS_NVRAM_AS1          0xfef880d0U
 #define MCPN765_PHYS_NVRAM_DATA         0xfef880d8U
-
 
 extern void mcpn765_find_bridges(void);
 
diff -Nru a/arch/ppc/platforms/mcpn765_serial.h b/arch/ppc/platforms/mcpn765_serial.h
--- a/arch/ppc/platforms/mcpn765_serial.h	2003-09-12 09:26:53 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,64 +0,0 @@
-/*
- * include/asm-ppc/mcpn765_serial.h
- *
- * Definitions for Motorola MCG MCPN765 cPCI board support
- *
- * Author: Mark A. Greer
- *         mgreer@mvista.com
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASMPPC_MCPN765_SERIAL_H
-#define __ASMPPC_MCPN765_SERIAL_H
-
-#include <linux/config.h>
-
-/* Define the UART base addresses */
-#define	MCPN765_SERIAL_1		0xfef88000
-#define	MCPN765_SERIAL_2		0xfef88200
-#define	MCPN765_SERIAL_3		0xfef88400
-#define	MCPN765_SERIAL_4		0xfef88600
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE  64
-#else
-#define RS_TABLE_SIZE  4
-#endif
-
-/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
-#define BASE_BAUD	( 1843200 / 16 )
-#define UART_CLK	1843200
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-/* All UART IRQ's are wire-OR'd to IRQ 17 */
-#define STD_SERIAL_PORT_DFNS \
-        { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\
-		iomem_base: (u8 *)MCPN765_SERIAL_1,			\
-		iomem_reg_shift: 4,					\
-		io_type: SERIAL_IO_MEM },				\
-        { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\
-		iomem_base: (u8 *)MCPN765_SERIAL_2,			\
-		iomem_reg_shift: 4,					\
-		io_type: SERIAL_IO_MEM },				\
-        { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\
-		iomem_base: (u8 *)MCPN765_SERIAL_3,			\
-		iomem_reg_shift: 4,					\
-		io_type: SERIAL_IO_MEM },				\
-        { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\
-		iomem_base: (u8 *)MCPN765_SERIAL_4,			\
-		iomem_reg_shift: 4,					\
-		io_type: SERIAL_IO_MEM },
-
-#define SERIAL_PORT_DFNS \
-        STD_SERIAL_PORT_DFNS
-
-#endif /* __ASMPPC_MCPN765_SERIAL_H */
diff -Nru a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/mvme5100.c	2004-08-24 08:31:19 -07:00
@@ -0,0 +1,349 @@
+/*
+ * arch/ppc/platforms/mvme5100.c
+ *
+ * Board setup routines for the Motorola MVME5100.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/pci-bridge.h>
+#include <asm/bootinfo.h>
+#include <asm/hawk.h>
+
+#include <platforms/pplus.h>
+#include <platforms/mvme5100.h>
+
+static u_char mvme5100_openpic_initsenses[16] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* i8259 cascade */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* TL16C550 UART 1,2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet1 front panel or P2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Hawk Watchdog 1,2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* DS1621 thermal alarm */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT0# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT1# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT2# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT3# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTA#, PMC2 INTB# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTB#, PMC2 INTC# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTC#, PMC2 INTD# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTD#, PMC2 INTA# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet 2 (front panel) */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Abort Switch */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* RTC Alarm */
+};
+
+static inline int
+mvme5100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	int irq;
+
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{  0,  0,  0,  0 },	/* IDSEL 11 - Winbond */
+		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
+		{ 21, 22, 23, 24 },	/* IDSEL 13 - Universe II */
+		{ 18,  0,  0,  0 },	/* IDSEL 14 - Enet 1 */
+		{  0,  0,  0,  0 },	/* IDSEL 15 - unused */
+		{ 25, 26, 27, 28 },	/* IDSEL 16 - PMC Slot 1 */
+		{ 28, 25, 26, 27 },	/* IDSEL 17 - PMC Slot 2 */
+		{  0,  0,  0,  0 },	/* IDSEL 18 - unused */
+		{ 29,  0,  0,  0 },	/* IDSEL 19 - Enet 2 */
+		{  0,  0,  0,  0 },	/* IDSEL 20 - PMCSPAN */
+	};
+
+	const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4;
+	irq = PCI_IRQ_TABLE_LOOKUP;
+	/* If lookup is zero, always return 0 */
+	if (!irq)
+		return 0;
+	else
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+	/* If IPMC761 present, return table value */
+	return irq;
+#else
+	/* If IPMC761 not present, we don't have an i8259 so adjust */
+	return (irq - NUM_8259_INTERRUPTS);
+#endif
+}
+
+static void
+mvme5100_pcibios_fixup_resources(struct pci_dev *dev)
+{
+	int i;
+
+	if ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+			(dev->device == PCI_DEVICE_ID_MOTOROLA_HAWK))
+		for (i=0; i<DEVICE_COUNT_RESOURCE; i++)
+		{
+			dev->resource[i].start = 0;
+			dev->resource[i].end = 0;
+		}
+}
+
+static void __init
+mvme5100_setup_bridge(void)
+{
+	struct pci_controller*	hose;
+
+	hose = pcibios_alloc_controller();
+
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->pci_mem_offset = MVME5100_PCI_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource, MVME5100_PCI_LOWER_IO,
+			MVME5100_PCI_UPPER_IO, IORESOURCE_IO,
+			"PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0], MVME5100_PCI_LOWER_MEM,
+			MVME5100_PCI_UPPER_MEM, IORESOURCE_MEM,
+			"PCI host bridge");
+
+	hose->io_space.start = MVME5100_PCI_LOWER_IO;
+	hose->io_space.end = MVME5100_PCI_UPPER_IO;
+	hose->mem_space.start = MVME5100_PCI_LOWER_MEM;
+	hose->mem_space.end = MVME5100_PCI_UPPER_MEM;
+	hose->io_base_virt = (void *)MVME5100_ISA_IO_BASE;
+
+	/* Use indirect method of Hawk */
+	setup_indirect_pci(hose, MVME5100_PCI_CONFIG_ADDR,
+			MVME5100_PCI_CONFIG_DATA);
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pcibios_fixup_resources = mvme5100_pcibios_fixup_resources;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mvme5100_map_irq;
+}
+
+static void __init
+mvme5100_setup_arch(void)
+{
+	if ( ppc_md.progress )
+		ppc_md.progress("mvme5100_setup_arch: enter", 0);
+
+	loops_per_jiffy = 50000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	if ( ppc_md.progress )
+		ppc_md.progress("mvme5100_setup_arch: find_bridges", 0);
+
+	/* Setup PCI host bridge */
+	mvme5100_setup_bridge();
+
+	/* Find and map our OpenPIC */
+	hawk_mpic_init(MVME5100_PCI_MEM_OFFSET);
+	OpenPIC_InitSenses = mvme5100_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(mvme5100_openpic_initsenses);
+
+	printk("MVME5100 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+
+	if ( ppc_md.progress )
+		ppc_md.progress("mvme5100_setup_arch: exit", 0);
+
+	return;
+}
+
+static void __init
+mvme5100_init2(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+		request_region(0x00,0x20,"dma1");
+		request_region(0x20,0x20,"pic1");
+		request_region(0x40,0x20,"timer");
+		request_region(0x80,0x10,"dma page reg");
+		request_region(0xa0,0x20,"pic2");
+		request_region(0xc0,0x20,"dma2");
+#endif
+	return;
+}
+
+/*
+ * Interrupt setup and service.
+ * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC.
+ */
+static void __init
+mvme5100_init_IRQ(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+	int i;
+#endif
+
+	if ( ppc_md.progress )
+		ppc_md.progress("init_irq: enter", 0);
+
+	openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+	openpic_init(NUM_8259_INTERRUPTS);
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			&i8259_irq);
+
+	/* Map i8259 interrupts. */
+	for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	i8259_init(NULL);
+#else
+	openpic_init(0);
+#endif
+
+	if ( ppc_md.progress )
+		ppc_md.progress("init_irq: exit", 0);
+
+	return;
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+mvme5100_set_bat(void)
+{
+	mb();
+	mtspr(DBAT1U, 0xf0001ffe);
+	mtspr(DBAT1L, 0xf000002a);
+	mb();
+}
+
+static unsigned long __init
+mvme5100_find_end_of_memory(void)
+{
+	return hawk_get_mem_size(MVME5100_HAWK_SMC_BASE);
+}
+
+static void __init
+mvme5100_map_io(void)
+{
+	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+	ioremap_base = 0xfe000000;
+}
+
+static void
+mvme5100_reset_board(void)
+{
+	local_irq_disable();
+
+	/* Set exception prefix high - to the firmware */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	out_8((u_char *)MVME5100_BOARD_MODRST_REG, 0x01);
+
+	return;
+}
+
+static void
+mvme5100_restart(char *cmd)
+{
+	volatile ulong i = 10000000;
+
+	mvme5100_reset_board();
+
+	while (i-- > 0);
+	panic("restart failed\n");
+}
+
+static void
+mvme5100_halt(void)
+{
+	local_irq_disable();
+	while (1);
+}
+
+static void
+mvme5100_power_off(void)
+{
+	mvme5100_halt();
+}
+
+static int
+mvme5100_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Motorola\n");
+	seq_printf(m, "machine\t\t: MVME5100\n");
+
+	return 0;
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+	mvme5100_set_bat();
+
+	isa_io_base = MVME5100_ISA_IO_BASE;
+	isa_mem_base = MVME5100_ISA_MEM_BASE;
+	pci_dram_offset = MVME5100_PCI_DRAM_OFFSET;
+
+	ppc_md.setup_arch = mvme5100_setup_arch;
+	ppc_md.show_cpuinfo = mvme5100_show_cpuinfo;
+	ppc_md.init_IRQ = mvme5100_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+	ppc_md.init = mvme5100_init2;
+
+	ppc_md.restart = mvme5100_restart;
+	ppc_md.power_off = mvme5100_power_off;
+	ppc_md.halt = mvme5100_halt;
+
+	ppc_md.find_end_of_memory = mvme5100_find_end_of_memory;
+	ppc_md.setup_io_mappings = mvme5100_map_io;
+
+	TODC_INIT(TODC_TYPE_MK48T37, MVME5100_NVRAM_AS0, MVME5100_NVRAM_AS1,
+			MVME5100_NVRAM_DATA, 8);
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_m48txx_read_val;
+	ppc_md.nvram_write_val = todc_m48txx_write_val;
+}
diff -Nru a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h
--- a/arch/ppc/platforms/mvme5100.h	2003-09-12 09:26:53 -07:00
+++ b/arch/ppc/platforms/mvme5100.h	2004-08-12 16:44:46 -07:00
@@ -63,10 +63,29 @@
 #define MVME5100_SERIAL_IRQ		1
 #endif
 
-#define MVME5100_WINBOND_DEVFN		0x58
-#define MVME5100_WINBOND_VIDDID		0x056510ad
+#define RS_TABLE_SIZE  4
 
-extern void mvme5100_setup_bridge(void);
+#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 )
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* All UART IRQ's are wire-OR'd to one MPIC IRQ */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, MVME5100_SERIAL_1, \
+		MVME5100_SERIAL_IRQ, \
+		STD_COM_FLAGS, /* ttyS0 */ \
+		iomem_base: (unsigned char *)MVME5100_SERIAL_1,		\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MVME5100_SERIAL_2, \
+		MVME5100_SERIAL_IRQ, \
+		STD_COM_FLAGS, /* ttyS1 */ \
+		iomem_base: (unsigned char *)MVME5100_SERIAL_2,		\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
 
 #endif /* __ASM_MVME5100_H__ */
 #endif /* __KERNEL__ */
diff -Nru a/arch/ppc/platforms/mvme5100_pci.c b/arch/ppc/platforms/mvme5100_pci.c
--- a/arch/ppc/platforms/mvme5100_pci.c	2003-09-12 09:26:53 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,121 +0,0 @@
-/*
- * arch/ppc/platforms/mvme5100_pci.c
- *
- * PCI setup routines for the Motorola MVME5100.
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <platforms/mvme5100.h>
-#include <asm/pplus.h>
-
-static inline int
-mvme5100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	int irq;
-
-	static char pci_irq_table[][4] =
-	/*
-	 *	PCI IDSEL/INTPIN->INTLINE
-	 * 	   A   B   C   D
-	 */
-	{
-		{  0,  0,  0,  0 },	/* IDSEL 11 - Winbond */
-		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
-		{ 21, 22, 23, 24 },	/* IDSEL 13 - Universe II */
-		{ 18,  0,  0,  0 },	/* IDSEL 14 - Enet 1 */
-		{  0,  0,  0,  0 },	/* IDSEL 15 - unused */
-		{ 25, 26, 27, 28 },	/* IDSEL 16 - PMC Slot 1 */
-		{ 28, 25, 26, 27 },	/* IDSEL 17 - PMC Slot 2 */
-		{  0,  0,  0,  0 },	/* IDSEL 18 - unused */
-		{ 29,  0,  0,  0 },	/* IDSEL 19 - Enet 2 */
-		{  0,  0,  0,  0 },	/* IDSEL 20 - PMCSPAN */
-	};
-
-	const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4;
-	irq = PCI_IRQ_TABLE_LOOKUP;
-	/* If lookup is zero, always return 0 */
-	if (!irq)
-		return 0;
-	else
-#ifdef CONFIG_MVME5100_IPMC761_PRESENT
-	/* If IPMC761 present, return table value */
-	return irq;
-#else
-	/* If IPMC761 not present, we don't have an i8259 so adjust */
-	return (irq - NUM_8259_INTERRUPTS);
-#endif
-}
-
-static void
-mvme5100_pcibios_fixup_resources(struct pci_dev *dev)
-{
-	int i;
-
-	if ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
-			(dev->device == PCI_DEVICE_ID_MOTOROLA_HAWK))
-		for (i=0; i<DEVICE_COUNT_RESOURCE; i++)
-		{
-			dev->resource[i].start = 0;
-			dev->resource[i].end = 0;
-		}
-}
-
-void __init
-mvme5100_setup_bridge(void)
-{
-	struct pci_controller*	hose;
-
-	hose = pcibios_alloc_controller();
-
-	if (!hose)
-		return;
-
-	hose->first_busno = 0;
-	hose->last_busno = 0xff;
-	hose->pci_mem_offset = MVME5100_PCI_MEM_OFFSET;
-
-	pci_init_resource(&hose->io_resource,
-			MVME5100_PCI_LOWER_IO,
-			MVME5100_PCI_UPPER_IO,
-			IORESOURCE_IO,
-			"PCI host bridge");
-
-	pci_init_resource(&hose->mem_resources[0],
-			MVME5100_PCI_LOWER_MEM,
-			MVME5100_PCI_UPPER_MEM,
-			IORESOURCE_MEM,
-			"PCI host bridge");
-
-	hose->io_space.start = MVME5100_PCI_LOWER_IO;
-	hose->io_space.end = MVME5100_PCI_UPPER_IO;
-	hose->mem_space.start = MVME5100_PCI_LOWER_MEM;
-	hose->mem_space.end = MVME5100_PCI_UPPER_MEM;
-	hose->io_base_virt = (void *)MVME5100_ISA_IO_BASE;
-
-	/* Use indirect method of Hawk */
-	setup_indirect_pci(hose,
-			   MVME5100_PCI_CONFIG_ADDR,
-			   MVME5100_PCI_CONFIG_DATA);
-
-	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
-	ppc_md.pcibios_fixup_resources = mvme5100_pcibios_fixup_resources;
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mvme5100_map_irq;
-}
diff -Nru a/arch/ppc/platforms/mvme5100_serial.h b/arch/ppc/platforms/mvme5100_serial.h
--- a/arch/ppc/platforms/mvme5100_serial.h	2003-09-12 09:26:53 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,54 +0,0 @@
-/*
- * include/asm-ppc/mvme5100_serial.h
- *
- * Definitions for Motorola MVME5100 support
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_MVME5100_SERIAL_H__
-#define __ASM_MVME5100_SERIAL_H__
-
-#include <linux/config.h>
-#include <platforms/mvme5100.h>
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE  64
-#else
-#define RS_TABLE_SIZE  4
-#endif
-
-#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 )
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-/* All UART IRQ's are wire-OR'd to one MPIC IRQ */
-#define STD_SERIAL_PORT_DFNS \
-        { 0, BASE_BAUD, MVME5100_SERIAL_1, \
-		MVME5100_SERIAL_IRQ, \
-		STD_COM_FLAGS, /* ttyS0 */ \
-		iomem_base: (unsigned char *)MVME5100_SERIAL_1,		\
-		iomem_reg_shift: 4,					\
-		io_type: SERIAL_IO_MEM },				\
-        { 0, BASE_BAUD, MVME5100_SERIAL_2, \
-		MVME5100_SERIAL_IRQ, \
-		STD_COM_FLAGS, /* ttyS1 */ \
-		iomem_base: (unsigned char *)MVME5100_SERIAL_2,		\
-		iomem_reg_shift: 4,					\
-		io_type: SERIAL_IO_MEM },
-
-#define SERIAL_PORT_DFNS \
-        STD_SERIAL_PORT_DFNS
-
-#endif /* __ASM_MVME5100_SERIAL_H__ */
-#endif /* __KERNEL__ */
diff -Nru a/arch/ppc/platforms/mvme5100_setup.c b/arch/ppc/platforms/mvme5100_setup.c
--- a/arch/ppc/platforms/mvme5100_setup.c	2004-04-28 00:21:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,284 +0,0 @@
-/*
- * arch/ppc/platforms/mvme5100_setup.c
- *
- * Board setup routines for the Motorola MVME5100.
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/time.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/open_pic.h>
-#include <asm/i8259.h>
-#include <platforms/mvme5100.h>
-#include <asm/todc.h>
-#include <asm/pci-bridge.h>
-#include <asm/bootinfo.h>
-#include <asm/pplus.h>
-
-extern char cmd_line[];
-
-static u_char mvme5100_openpic_initsenses[] __initdata = {
-	0,	/* 16: i8259 cascade (active high) */
-	1,	/* 17: TL16C550 UART 1,2 */
-	1,	/* 18: Enet 1 (front panel or P2) */
-	1,	/* 19: Hawk Watchdog 1,2 */
-	1,	/* 20: DS1621 thermal alarm */
-	1,	/* 21: Universe II LINT0# */
-	1,	/* 22: Universe II LINT1# */
-	1,	/* 23: Universe II LINT2# */
-	1,	/* 24: Universe II LINT3# */
-	1,	/* 25: PMC1 INTA#, PMC2 INTB# */
-	1,	/* 26: PMC1 INTB#, PMC2 INTC# */
-	1,	/* 27: PMC1 INTC#, PMC2 INTD# */
-	1,	/* 28: PMC1 INTD#, PMC2 INTA# */
-	1,	/* 29: Enet 2 (front panel) */
-	1,	/* 30: Abort Switch */
-	1,	/* 31: RTC Alarm */
-};
-
-static void __init
-mvme5100_setup_arch(void)
-{
-	if ( ppc_md.progress )
-		ppc_md.progress("mvme5100_setup_arch: enter", 0);
-
-	loops_per_jiffy = 50000000 / HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-#ifdef	CONFIG_ROOT_NFS
-		ROOT_DEV = Root_NFS;
-#else
-		ROOT_DEV = Root_SDA2;
-#endif
-
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
-	if ( ppc_md.progress )
-		ppc_md.progress("mvme5100_setup_arch: find_bridges", 0);
-
-	/* Setup PCI host bridge */
-	mvme5100_setup_bridge();
-
-	/* Find and map our OpenPIC */
-	pplus_mpic_init(MVME5100_PCI_MEM_OFFSET);
-	OpenPIC_InitSenses = mvme5100_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof(mvme5100_openpic_initsenses);
-
-	printk("MVME5100 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
-
-	if ( ppc_md.progress )
-		ppc_md.progress("mvme5100_setup_arch: exit", 0);
-
-	return;
-}
-
-static void __init
-mvme5100_init2(void)
-{
-#ifdef CONFIG_MVME5100_IPMC761_PRESENT
-		request_region(0x00,0x20,"dma1");
-		request_region(0x20,0x20,"pic1");
-		request_region(0x40,0x20,"timer");
-		request_region(0x80,0x10,"dma page reg");
-		request_region(0xa0,0x20,"pic2");
-		request_region(0xc0,0x20,"dma2");
-#endif
-	return;
-}
-
-/*
- * Interrupt setup and service.
- * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC.
- */
-static void __init
-mvme5100_init_IRQ(void)
-{
-#ifdef CONFIG_MVME5100_IPMC761_PRESENT
-	int i;
-#endif
-
-	if ( ppc_md.progress )
-		ppc_md.progress("init_irq: enter", 0);
-
-#ifdef CONFIG_MVME5100_IPMC761_PRESENT
-	openpic_init(1, NUM_8259_INTERRUPTS, NULL, -1);
-	openpic_hookup_cascade(NUM_8259_INTERRUPTS,"82c59 cascade",&i8259_irq);
-
-	for(i=0; i < NUM_8259_INTERRUPTS; i++)
-		irq_desc[i].handler = &i8259_pic;
-
-	i8259_init(NULL);
-#else
-	openpic_init(1, 0, NULL, -1);
-#endif
-
-	if ( ppc_md.progress )
-		ppc_md.progress("init_irq: exit", 0);
-
-	return;
-}
-
-/*
- * Set BAT 3 to map 0xf0000000 to end of physical memory space.
- */
-static __inline__ void
-mvme5100_set_bat(void)
-{
-	unsigned long bat3u, bat3l;
-	static int mapping_set = 0;
-
-	if (!mapping_set) {
-
-		__asm__ __volatile__(
-		" lis %0,0xf000\n \
-		  ori %1,%0,0x002a\n \
-		  ori %0,%0,0x1ffe\n \
-		  mtspr 0x21e,%0\n \
-		  mtspr 0x21f,%1\n \
-		  isync\n \
-		  sync "
-		: "=r" (bat3u), "=r" (bat3l));
-
-		mapping_set = 1;
-	}
-
-	return;
-}
-
-static unsigned long __init
-mvme5100_find_end_of_memory(void)
-{
-	mvme5100_set_bat();
-	return pplus_get_mem_size(MVME5100_HAWK_SMC_BASE);
-}
-
-static void __init
-mvme5100_map_io(void)
-{
-	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
-	ioremap_base = 0xfe000000;
-}
-
-static void
-mvme5100_reset_board(void)
-{
-	local_irq_disable();
-
-	/* Set exception prefix high - to the firmware */
-	_nmask_and_or_msr(0, MSR_IP);
-
-	out_8((u_char *)MVME5100_BOARD_MODRST_REG, 0x01);
-
-	return;
-}
-
-static void
-mvme5100_restart(char *cmd)
-{
-	volatile ulong i = 10000000;
-
-	mvme5100_reset_board();
-
-	while (i-- > 0);
-	panic("restart failed\n");
-}
-
-static void
-mvme5100_halt(void)
-{
-	local_irq_disable();
-	while (1);
-}
-
-static void
-mvme5100_power_off(void)
-{
-	mvme5100_halt();
-}
-
-static int
-mvme5100_show_cpuinfo(struct seq_file *m)
-{
-	seq_printf(m, "vendor\t\t: Motorola\n");
-	seq_printf(m, "machine\t\t: MVME5100\n");
-
-	return 0;
-}
-
-TODC_ALLOC();
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
-{
-	parse_bootinfo(find_bootinfo());
-
-	isa_io_base = MVME5100_ISA_IO_BASE;
-	isa_mem_base = MVME5100_ISA_MEM_BASE;
-	pci_dram_offset = MVME5100_PCI_DRAM_OFFSET;
-
-	ppc_md.setup_arch = mvme5100_setup_arch;
-	ppc_md.show_cpuinfo = mvme5100_show_cpuinfo;
-	ppc_md.init_IRQ = mvme5100_init_IRQ;
-	ppc_md.get_irq = openpic_get_irq;
-	ppc_md.init = mvme5100_init2;
-
-	ppc_md.restart = mvme5100_restart;
-	ppc_md.power_off = mvme5100_power_off;
-	ppc_md.halt = mvme5100_halt;
-
-	ppc_md.find_end_of_memory = mvme5100_find_end_of_memory;
-	ppc_md.setup_io_mappings = mvme5100_map_io;
-
-	TODC_INIT(TODC_TYPE_MK48T37,
-		  MVME5100_NVRAM_AS0,
-		  MVME5100_NVRAM_AS1,
-		  MVME5100_NVRAM_DATA,
-		  8);
-
-	ppc_md.time_init = todc_time_init;
-	ppc_md.set_rtc_time = todc_set_rtc_time;
-	ppc_md.get_rtc_time = todc_get_rtc_time;
-	ppc_md.calibrate_decr = todc_calibrate_decr;
-
-	ppc_md.nvram_read_val = todc_m48txx_read_val;
-	ppc_md.nvram_write_val = todc_m48txx_write_val;
-
-	ppc_md.progress = NULL;
-}
diff -Nru a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c
--- a/arch/ppc/platforms/pcore.c	2004-04-09 10:51:08 -07:00
+++ b/arch/ppc/platforms/pcore.c	2004-08-16 09:04:08 -07:00
@@ -228,10 +228,6 @@
 		ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
  	printk(KERN_INFO "Force PowerCore ");
 	if (board_type == PCORE_TYPE_6750)
 		printk("6750\n");
diff -Nru a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
--- a/arch/ppc/platforms/pmac_setup.c	2004-06-24 01:55:46 -07:00
+++ b/arch/ppc/platforms/pmac_setup.c	2004-08-16 09:04:08 -07:00
@@ -318,9 +318,6 @@
 #ifdef CONFIG_NVRAM
 	pmac_nvram_init();
 #endif
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
 		ROOT_DEV = Root_RAM0;
diff -Nru a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h
--- a/arch/ppc/platforms/powerpmc250.h	2003-09-12 09:26:54 -07:00
+++ b/arch/ppc/platforms/powerpmc250.h	2004-08-12 15:19:29 -07:00
@@ -7,7 +7,7 @@
  *
  * Borrowed heavily from prpmc750.h by Matt Porter <mporter@mvista.com>
  *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
  * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
@@ -16,8 +16,6 @@
 #ifndef __ASMPPC_POWERPMC250_H
 #define __ASMPPC_POWERPMC250_H
 
-#include <linux/serial_reg.h>
-
 #define POWERPMC250_PCI_CONFIG_ADDR	0x80000cf8
 #define POWERPMC250_PCI_CONFIG_DATA	0x80000cfc
 
@@ -36,5 +34,19 @@
 #define POWERPMC250_BASE_BAUD		12288000
 #define POWERPMC250_SERIAL		0xff000000
 #define POWERPMC250_SERIAL_IRQ		20
+
+/* UART Defines. */
+#define RS_TABLE_SIZE  1
+
+#define BASE_BAUD  (POWERPMC250_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+	{ 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ,	\
+		STD_COM_FLAGS, 				/* ttyS0 */	\
+		iomem_base: (u8 *)POWERPMC250_SERIAL,			\
+		iomem_reg_shift: 0,					\
+		io_type: SERIAL_IO_MEM }
 
 #endif /* __ASMPPC_POWERPMC250_H */
diff -Nru a/arch/ppc/platforms/powerpmc250_serial.h b/arch/ppc/platforms/powerpmc250_serial.h
--- a/arch/ppc/platforms/powerpmc250_serial.h	2003-09-12 09:26:54 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,40 +0,0 @@
-/*
- * include/asm-ppc/platforms/powerpmc250_serial.h
- *
- * Motorola PrPMC750 serial support
- *
- * Author: Troy Benjegerdes <tbenjegerdes@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifdef __KERNEL__
-#ifndef __ASMPPC_POWERPMC250_SERIAL_H
-#define __ASMPPC_POWERPMC250_SERIAL_H
-
-#include <linux/config.h>
-#include <platforms/powerpmc250.h>
-
-#define RS_TABLE_SIZE  1
-
-#define BASE_BAUD  (POWERPMC250_BASE_BAUD / 16)
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
-#endif
-
-#define SERIAL_PORT_DFNS \
-{ 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ, STD_COM_FLAGS, /* ttyS0 */\
-		iomem_base: (u8 *)POWERPMC250_SERIAL,		\
-		iomem_reg_shift: 0,					\
-		io_type: SERIAL_IO_MEM }
-
-#endif
-#endif /* __KERNEL__ */
diff -Nru a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
--- a/arch/ppc/platforms/pplus.c	2004-06-24 01:55:46 -07:00
+++ b/arch/ppc/platforms/pplus.c	2004-08-16 09:04:08 -07:00
@@ -583,8 +583,6 @@
 	vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE,
 						   0x08000000);
 	conswitchp = &vga_con;
-#elif defined(CONFIG_DUMMY_CONSOLE)
-	conswitchp = &dummy_con;
 #endif
 #ifdef CONFIG_PPCBUG_NVRAM
 	/* Read in NVRAM data */
diff -Nru a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/pq2ads.c	2004-08-13 16:33:54 -07:00
@@ -0,0 +1,26 @@
+/*
+ * arch/ppc/platforms/pq2ads.c
+ *
+ * PQ2ADS platform support
+ *
+ * Author: Kumar Gala <kumar.gala@freescale.com>
+ * Derived from: est8260_setup.c by Allen Curtis
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * 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 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mpc8260.h>
+
+void __init
+m82xx_board_init(void)
+{
+	/* Enable the 2nd UART port */
+        *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
+}
diff -Nru a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
--- a/arch/ppc/platforms/pq2ads.h	2004-06-16 11:22:36 -07:00
+++ b/arch/ppc/platforms/pq2ads.h	2004-08-13 14:03:33 -07:00
@@ -23,6 +23,10 @@
 
 #define BOOTROM_RESTART_ADDR	((uint)0xff000104)
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Motorola"
+#define CPUINFO_MACHINE		"PQ2 ADS PowerPC"
+
 /* The ADS8260 has 16, 32-bit wide control/status registers, accessed
  * only on word boundaries.
  * Not all are used (yet), or are interesting to us (yet).
diff -Nru a/arch/ppc/platforms/pq2ads_setup.c b/arch/ppc/platforms/pq2ads_setup.c
--- a/arch/ppc/platforms/pq2ads_setup.c	2004-06-17 00:32:04 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,66 +0,0 @@
-/*
- * arch/ppc/platforms/pq2ads_setup.c
- *
- * PQ2ADS platform support
- *
- * Author: Kumar Gala <kumar.gala@freescale.com>
- * Derived from: est8260_setup.c by Allen Curtis
- *
- * Copyright 2004 Freescale Semiconductor, Inc.
- *
- * 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 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/seq_file.h>
-
-#include <asm/mpc8260.h>
-#include <asm/machdep.h>
-
-static void (*callback_setup_arch)(void);
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void m8260_init(unsigned long r3, unsigned long r4,
-	unsigned long r5, unsigned long r6, unsigned long r7);
-
-static int
-pq2ads_show_cpuinfo(struct seq_file *m)
-{
-	bd_t	*binfo = (bd_t *)__res;
-
-	seq_printf(m, "vendor\t\t: Motorola\n"
-		      "machine\t\t: PQ2 ADS PowerPC\n"
-		      "\n"
-		      "mem size\t\t: 0x%08lx\n"
-		      "console baud\t\t: %ld\n"
-		      "\n",
-		      binfo->bi_memsize,
-		      binfo->bi_baudrate);
-	return 0;
-}
-
-static void __init
-pq2ads_setup_arch(void)
-{
-	printk("PQ2 ADS Port\n");
-	callback_setup_arch();
-        *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
-}
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
-{
-	/* Generic 8260 platform initialization */
-	m8260_init(r3, r4, r5, r6, r7);
-
-	/* Anything special for this platform */
-	ppc_md.show_cpuinfo	= pq2ads_show_cpuinfo;
-
-	callback_setup_arch	= ppc_md.setup_arch;
-	ppc_md.setup_arch	= pq2ads_setup_arch;
-}
diff -Nru a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c
--- a/arch/ppc/platforms/prep_pci.c	2004-07-26 11:42:57 -07:00
+++ b/arch/ppc/platforms/prep_pci.c	2004-08-16 10:56:27 -07:00
@@ -836,52 +836,59 @@
 void __init
 ibm_prep_init(void)
 {
-#ifdef CONFIG_PREP_RESIDUAL
-	u32 addr, real_addr, len;
-	PPC_DEVICE *mpic;
-	PnP_TAG_PACKET *pkt;
-
-	/* Use the PReP residual data to determine if an OpenPIC is
-	 * present.  If so, get the large vendor packet which will
-	 * tell us the base address and length in memory.
-	 * If we are successful, ioremap the memory area and set
-	 * OpenPIC_Addr (this indicates that the OpenPIC was found).
-	 */
-	mpic = residual_find_device(-1, NULL, SystemPeripheral,
-			    ProgrammableInterruptController, MPIC, 0);
-	if (!mpic)
-		return;
+	if (have_residual_data) {
+		u32 addr, real_addr, len, offset;
+		PPC_DEVICE *mpic;
+		PnP_TAG_PACKET *pkt;
+
+		/* Use the PReP residual data to determine if an OpenPIC is
+		 * present.  If so, get the large vendor packet which will
+		 * tell us the base address and length in memory.
+		 * If we are successful, ioremap the memory area and set
+		 * OpenPIC_Addr (this indicates that the OpenPIC was found).
+		 */
+		mpic = residual_find_device(-1, NULL, SystemPeripheral,
+				    ProgrammableInterruptController, MPIC, 0);
+		if (!mpic)
+			return;
 
-	pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
-			mpic->AllocatedOffset, 9, 0);
+		pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+				mpic->AllocatedOffset, 9, 0);
 
-	if (!pkt)
-		return;
+		if (!pkt)
+			return;
 
 #define p pkt->L4_Pack.L4_Data.L4_PPCPack
-	if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32)))
-		return; /* not a 32-bit memory address */
-
-	real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
-	if (real_addr == 0xffffffff)
-		return;
-
-	/* Adjust address to be as seen by CPU */
-	addr = real_addr + PREP_ISA_MEM_BASE;
+	 	if (p.PPCData[1] == 32) {
+			switch (p.PPCData[0]) {
+				case 1:  offset = PREP_ISA_IO_BASE;  break;
+				case 2:  offset = PREP_ISA_MEM_BASE; break;
+				default: return; /* Not I/O or memory?? */
+			}
+		}
+		else
+			return; /* Not a 32-bit address */
 
-	len = ld_le32((unsigned int *) (p.PPCData + 12));
-	if (!len)
-		return;
+		real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
+		if (real_addr == 0xffffffff)
+			return;
+
+		/* Adjust address to be as seen by CPU */
+		addr = real_addr + offset;
+
+		len = ld_le32((unsigned int *) (p.PPCData + 12));
+		if (!len)
+			return;
 #undef p
-	OpenPIC_Addr = ioremap(addr, len);
-	ppc_md.get_irq = openpic_get_irq;
+		OpenPIC_Addr = ioremap(addr, len);
+		ppc_md.get_irq = openpic_get_irq;
 
-	OpenPIC_InitSenses = prep_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
+		OpenPIC_InitSenses = prep_openpic_initsenses;
+		OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
 
-	printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
-	       "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
-#endif
+		printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
+		       "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
+	}
 }
 
 static void __init
@@ -901,6 +908,17 @@
 }
 
 void __init
+prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	if (have_residual_data) {
+		Motherboard_map_name = res->VitalProductData.PrintableModel;
+		Motherboard_map = NULL;
+		Motherboard_routes = NULL;
+		residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi);
+	}
+}
+
+void __init
 prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
 {
 	Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)";
@@ -1011,21 +1029,31 @@
 		}
 	} else if ( _prep_type == _PREP_IBM ) {
 		unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
+		unsigned short irq_edge_mask;
+		int i;
 
 		setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi);
 
 		outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */
 		outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */
+
+		irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo;
+		for (i = 0; i < 16; ++i, irq_edge_mask >>= 1)
+			if (irq_edge_mask & 1)
+				irq_desc[i].status |= IRQ_LEVEL;
 	} else {
 		printk("No known machine pci routing!\n");
 		return;
 	}
 
 	/* Set up mapping from slots */
-	for (i = 1;  i <= 4;  i++)
-		ibc_pirq[i-1] = Motherboard_routes[i];
-	/* Enable PCI interrupts */
-	*ibc_pcicon |= 0x20;
+	if (Motherboard_routes) {
+		for (i = 1;  i <= 4;  i++)
+			ibc_pirq[i-1] = Motherboard_routes[i];
+
+		/* Enable PCI interrupts */
+		*ibc_pcicon |= 0x20;
+	}
 }
 
 void __init
@@ -1171,38 +1199,52 @@
 prep_pcibios_fixup(void)
 {
         struct pci_dev *dev = NULL;
+	int irq;
+	int have_openpic = (OpenPIC_Addr != NULL);
 
 	prep_route_pci_interrupts();
 
 	printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
-	if (OpenPIC_Addr) {
-		/* PCI interrupts are controlled by the OpenPIC */
-		while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-			if (dev->bus->number == 0) {
-                       		dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
-				pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-			} else {
-				if (Motherboard_non0 != NULL)
-					Motherboard_non0(dev);
-			}
-		}
-
-		/* Setup the Winbond or Via PIB */
-		prep_pib_init();
-
-		return;
-	}
 
-	dev = NULL;
+	/* Iterate through all the PCI devices, setting the IRQ */
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 		/*
-		 * Use our old hard-coded kludge to figure out what
-		 * irq this device uses.  This is necessary on things
-		 * without residual data. -- Cort
+		 * If we have residual data, then this is easy: query the
+		 * residual data for the IRQ line allocated to the device.
+		 * This works the same whether we have an OpenPic or not.
+		 */
+		if (have_residual_data) {
+			irq = residual_pcidev_irq(dev);
+			dev->irq = have_openpic ? openpic_to_irq(irq) : irq;
+		}
+		/*
+		 * If we don't have residual data, then we need to use
+		 * tables to determine the IRQ.  The table organisation
+		 * is different depending on whether there is an OpenPIC
+		 * or not.  The tables are only used for bus 0, so check
+		 * this first.
 		 */
-		unsigned char d = PCI_SLOT(dev->devfn);
-		dev->irq = Motherboard_routes[Motherboard_map[d]];
+		else if (dev->bus->number == 0) {
+			irq = Motherboard_map[PCI_SLOT(dev->devfn)];
+			dev->irq = have_openpic ? openpic_to_irq(irq)
+						: Motherboard_routes[irq];
+		}
+		/*
+		 * Finally, if we don't have residual data and the bus is
+		 * non-zero, use the callback (if provided)
+		 */
+		else {
+			if (Motherboard_non0 != NULL)
+				Motherboard_non0(dev);
+
+			continue;
+		}
+
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 	}
+
+	/* Setup the Winbond or Via PIB */
+	prep_pib_init();
 }
 
 static void __init
@@ -1262,14 +1304,15 @@
 			   PREP_ISA_IO_BASE + 0xcfc);
 
 	printk("PReP architecture\n");
-#ifdef CONFIG_PREP_RESIDUAL
-	{
+
+	if (have_residual_data) {
 		PPC_DEVICE *hostbridge;
 
 		hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
 			BridgeController, PCIBridge, -1, 0);
 		if (hostbridge &&
-			hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
+			((hostbridge->DeviceId.Interface == PCIBridgeIndirect) ||
+			 (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) {
 			PnP_TAG_PACKET * pkt;
 			pkt = PnP_find_large_vendor_packet(
 				res->DevicePnPHeap+hostbridge->AllocatedOffset,
@@ -1284,7 +1327,6 @@
 				setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
 		}
 	}
-#endif /* CONFIG_PREP_RESIDUAL */
 
 	ppc_md.pcibios_fixup = prep_pcibios_fixup;
 	ppc_md.pcibios_after_init = prep_pcibios_after_init;
diff -Nru a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
--- a/arch/ppc/platforms/prep_setup.c	2004-07-26 11:43:07 -07:00
+++ b/arch/ppc/platforms/prep_setup.c	2004-08-24 08:29:33 -07:00
@@ -79,6 +79,7 @@
 
 int _prep_type;
 
+extern void prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
 extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
 extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
 extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
@@ -193,9 +194,8 @@
 		seq_printf(m, "bad");
 	seq_printf(m, "\n");
 
-#ifdef CONFIG_PREP_RESIDUAL
 	/* print info about SIMMs */
-	if (res->ResidualLength != 0) {
+	if (have_residual_data) {
 		int i;
 		seq_printf(m, "simms\t\t: ");
 		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
@@ -207,7 +207,13 @@
 		}
 		seq_printf(m, "\n");
 	}
-#endif
+}
+
+static int __prep
+prep_gen_cpuinfo(struct seq_file *m)
+{
+	prep_ibm_cpuinfo(m);
+	return 0;
 }
 
 static int __prep
@@ -431,9 +437,8 @@
 	}
 
 no_l2:
-#ifdef CONFIG_PREP_RESIDUAL
 	/* print info about SIMMs */
-	if (res->ResidualLength != 0) {
+	if (have_residual_data) {
 		int i;
 		seq_printf(m, "simms\t\t: ");
 		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
@@ -445,18 +450,11 @@
 		}
 		seq_printf(m, "\n");
 	}
-#endif
 
 	return 0;
 }
 
 static void __prep
-prep_tiger1_progress(char *msg, unsigned short code)
-{
-	outw(code, PREP_IBM_DISP);
-}
-
-static void __prep
 prep_restart(char *cmd)
 {
 #define PREP_SP92	0x92	/* Special Port 92 */
@@ -561,14 +559,12 @@
 {
 	/* PREP's without residual data will give incorrect values here */
 	seq_printf(m, "clock\t\t: ");
-#ifdef CONFIG_PREP_RESIDUAL
-	if (res->ResidualLength)
+	if (have_residual_data)
 		seq_printf(m, "%ldMHz\n",
 			   (res->VitalProductData.ProcessorHz > 1024) ?
 			   res->VitalProductData.ProcessorHz / 1000000 :
 			   res->VitalProductData.ProcessorHz);
 	else
-#endif /* CONFIG_PREP_RESIDUAL */
 		seq_printf(m, "???\n");
 
 	return 0;
@@ -598,9 +594,10 @@
 	 * Get the needed resource informations from residual data.
 	 *
 	 */
-#ifdef CONFIG_PREP_RESIDUAL
-	audiodevice = residual_find_device(~0, NULL, MultimediaController,
-			AudioController, -1, 0);
+	if (have_residual_data)
+		audiodevice = residual_find_device(~0, NULL,
+				MultimediaController, AudioController, -1, 0);
+
 	if (audiodevice != NULL) {
 		PnP_TAG_PACKET *pkt;
 
@@ -613,7 +610,6 @@
 		if (pkt != NULL)
 			ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);
 	}
-#endif
 
 	/*
 	 * These are the PReP specs' defaults for the cs4231.  We use these
@@ -649,13 +645,14 @@
 static void __init
 prep_init_vesa(void)
 {
-#if defined(CONFIG_PREP_RESIDUAL) && \
-	(defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \
+#if     (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \
 	 defined(CONFIG_FB_VESA))
-	PPC_DEVICE *vgadev;
+	PPC_DEVICE *vgadev = NULL;
+
+	if (have_residual_data)
+		vgadev = residual_find_device(~0, NULL, DisplayController,
+							SVGAController, -1, 0);
 
-	vgadev = residual_find_device(~0, NULL, DisplayController, SVGAController,
-									-1, 0);
 	if (vgadev != NULL) {
 		PnP_TAG_PACKET *pkt;
 
@@ -680,7 +677,112 @@
 			}
 		}
 	}
-#endif /* CONFIG_PREP_RESIDUAL */
+#endif
+}
+
+/*
+ * Set DBAT 2 to access 0x80000000 so early progress messages will work
+ */
+static __inline__ void
+prep_set_bat(void)
+{
+	/* wait for all outstanding memory access to complete */
+	mb();
+
+	/* setup DBATs */
+	mtspr(DBAT2U, 0x80001ffe);
+	mtspr(DBAT2L, 0x8000002a);
+
+	/* wait for updates */
+	mb();
+}
+
+/*
+ * IBM 3-digit status LED
+ */
+static unsigned int ibm_statusled_base __prepdata;
+
+static void __prep
+ibm_statusled_progress(char *s, unsigned short hex);
+
+static int __prep
+ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2,
+		    void * dummy3)
+{
+	ibm_statusled_progress(NULL, 0x505); /* SOS */
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ibm_statusled_block __prepdata = {
+	ibm_statusled_panic,
+	NULL,
+	INT_MAX /* try to do it first */
+};
+
+static void __prep
+ibm_statusled_progress(char *s, unsigned short hex)
+{
+	static int notifier_installed;
+	/*
+	 * Progress uses 4 digits and we have only 3.  So, we map 0xffff to
+	 * 0xfff for display switch off.  Out of range values are mapped to
+	 * 0xeff, as I'm told 0xf00 and above are reserved for hardware codes.
+	 * Install the panic notifier when the display is first switched off.
+	 */
+	if (hex == 0xffff) {
+		hex = 0xfff;
+		if (!notifier_installed) {
+			++notifier_installed;
+			notifier_chain_register(&panic_notifier_list,
+						&ibm_statusled_block);
+		}
+	}
+	else
+		if (hex > 0xfff)
+			hex = 0xeff;
+
+	mb();
+	outw(hex, ibm_statusled_base);
+}
+
+static void __init
+ibm_statusled_init(void)
+{
+	/*
+	 * The IBM 3-digit LED display is specified in the residual data
+	 * as an operator panel device, type "System Status LED".  Find
+	 * that device and determine its address.  We validate all the
+	 * other parameters on the off-chance another, similar device
+	 * exists.
+	 */
+	if (have_residual_data) {
+		PPC_DEVICE *led;
+		PnP_TAG_PACKET *pkt;
+
+		led = residual_find_device(~0, NULL, SystemPeripheral,
+					   OperatorPanel, SystemStatusLED, 0);
+		if (!led)
+			return;
+
+		pkt = PnP_find_packet((unsigned char *)
+		       &res->DevicePnPHeap[led->AllocatedOffset], S8_Packet, 0);
+		if (!pkt)
+			return;
+
+		if (pkt->S8_Pack.IOInfo != ISAAddr16bit)
+			return;
+		if (*(unsigned short *)pkt->S8_Pack.RangeMin !=
+		    *(unsigned short *)pkt->S8_Pack.RangeMax)
+			return;
+		if (pkt->S8_Pack.IOAlign != 2)
+			return;
+		if (pkt->S8_Pack.IONum != 2)
+			return;
+
+		ibm_statusled_base = ld_le16((unsigned short *)
+					     (pkt->S8_Pack.RangeMin));
+		ppc_md.progress = ibm_statusled_progress;
+	}
 }
 
 static void __init
@@ -706,7 +808,7 @@
 	{
 	case _PREP_IBM:
 		reg = inb(PREP_IBM_PLANAR);
-		printk(KERN_INFO "IBM planar ID: %08x", reg);
+		printk(KERN_INFO "IBM planar ID: %02x", reg);
 		switch (reg) {
 			case PREP_IBM_SANDALFOOT:
 				prep_gen_enable_l2();
@@ -721,7 +823,16 @@
 				ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo;
 				break;
 			default:
-				printk(" -- unknown! Assuming Carolina");
+				if (have_residual_data) {
+					prep_gen_enable_l2();
+					setup_ibm_pci = prep_residual_setup_pci;
+					ppc_md.power_off = prep_halt;
+					ppc_md.show_cpuinfo = prep_gen_cpuinfo;
+					break;
+				}
+				else
+					printk(" - unknown! Assuming Carolina");
+					/* fall through */
 			case PREP_IBM_CAROLINA_IDE_0:
 			case PREP_IBM_CAROLINA_IDE_1:
 			case PREP_IBM_CAROLINA_IDE_2:
@@ -745,7 +856,6 @@
 				setup_ibm_pci = prep_tiger1_setup_pci;
 				ppc_md.power_off = prep_sig750_poweroff;
 				ppc_md.show_cpuinfo = prep_tiger1_cpuinfo;
-				ppc_md.progress = prep_tiger1_progress;
 				break;
 		}
 		printk("\n");
@@ -808,8 +918,6 @@
 	/* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */
 	vgacon_remap_base = 0xf0000000;
 	conswitchp = &vga_con;
-#elif defined(CONFIG_DUMMY_CONSOLE)
-	conswitchp = &dummy_con;
 #endif
 }
 
@@ -821,18 +929,19 @@
 static void __init
 prep_calibrate_decr(void)
 {
-#ifdef CONFIG_PREP_RESIDUAL
-	unsigned long freq, divisor = 4;
+	if (have_residual_data) {
+		unsigned long freq, divisor = 4;
 
-	if ( res->VitalProductData.ProcessorBusHz ) {
-		freq = res->VitalProductData.ProcessorBusHz;
-		printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
-				(freq/divisor)/1000000,
-				(freq/divisor)%1000000);
-		tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
-		tb_ticks_per_jiffy = freq / HZ / divisor;
-	} else
-#endif
+		if ( res->VitalProductData.ProcessorBusHz ) {
+			freq = res->VitalProductData.ProcessorBusHz;
+			printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+					(freq/divisor)/1000000,
+					(freq/divisor)%1000000);
+			tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+			tb_ticks_per_jiffy = freq / HZ / divisor;
+		}
+	}
+	else
 		todc_calibrate_decr();
 }
 
@@ -863,6 +972,12 @@
 	}
 	for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
 		irq_desc[i].handler = &i8259_pic;
+
+	if (have_residual_data) {
+		i8259_init(residual_isapic_addr());
+		return;
+	}
+
 	/* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory
 	 * controller, we poll (as they have a different int-ack address). */
 	early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &pci_viddid);
@@ -1000,17 +1115,26 @@
 	DMA_MODE_WRITE = 0x48;
 
 	/* figure out what kind of prep workstation we are */
-#ifdef CONFIG_PREP_RESIDUAL
-	if ( res->ResidualLength != 0 ) {
+	if (have_residual_data) {
 		if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
 			_prep_type = _PREP_IBM;
 		else
 			_prep_type = _PREP_Motorola;
-	} else /* assume motorola if no residual (netboot?) */
-#endif
-	{
+	}
+	else {
+		/* assume motorola if no residual (netboot?) */
 		_prep_type = _PREP_Motorola;
 	}
+
+#ifdef CONFIG_PREP_PRESIDUAL
+	/* Switch off all residual data processing if the user requests it */
+	if (strstr(cmd_line, "noresidual") != NULL)
+			res = NULL;
+#endif
+
+	/* Initialise progress early to get maximum benefit */
+	prep_set_bat();
+	ibm_statusled_init();
 
 	ppc_md.setup_arch     = prep_setup_arch;
 	ppc_md.show_percpuinfo = prep_show_percpuinfo;
diff -Nru a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c
--- a/arch/ppc/platforms/prpmc750.c	2004-04-28 08:15:57 -07:00
+++ b/arch/ppc/platforms/prpmc750.c	2004-08-16 09:04:08 -07:00
@@ -193,10 +193,6 @@
 		ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	OpenPIC_InitSenses = prpmc750_openpic_initsenses;
 	OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses);
 
diff -Nru a/arch/ppc/platforms/prpmc750.h b/arch/ppc/platforms/prpmc750.h
--- a/arch/ppc/platforms/prpmc750.h	2004-04-28 00:21:32 -07:00
+++ b/arch/ppc/platforms/prpmc750.h	2004-08-12 15:19:29 -07:00
@@ -5,20 +5,16 @@
  *
  * Author: Matt Porter <mporter@mvista.com>
  *
- * Copyright 2001 MontaVista Software Inc.
- *
- * 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 of the  License, or (at your
- * option) any later version.
+ * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
  */
 
 #ifdef __KERNEL__
 #ifndef __ASM_PRPMC750_H__
 #define __ASM_PRPMC750_H__
 
-#include <linux/serial_reg.h>
-
 /*
  * Due to limiations imposed by legacy hardware (primaryily IDE controllers),
  * the PrPMC750 carrier board operates using a PReP address map.
@@ -80,6 +76,20 @@
 
 #define PRPMC750_TBEN_REG		0xfef880c0
 #define PRPMC750_TBEN_MASK		0x01
+
+/* UART Defines. */
+#define RS_TABLE_SIZE  4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (PRPMC750_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \
+		iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \
+		iomem_reg_shift: 4, \
+		io_type: SERIAL_IO_MEM } /* ttyS0 */
 
 #endif				/* __ASM_PRPMC750_H__ */
 #endif				/* __KERNEL__ */
diff -Nru a/arch/ppc/platforms/prpmc750_serial.h b/arch/ppc/platforms/prpmc750_serial.h
--- a/arch/ppc/platforms/prpmc750_serial.h	2003-09-12 09:26:54 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,43 +0,0 @@
-/*
- * include/asm-ppc/platforms/prpmc750_serial.h
- *
- * Motorola PrPMC750 serial support
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_PRPMC750_SERIAL_H__
-#define __ASM_PRPMC750_SERIAL_H__
-
-#include <linux/config.h>
-#include <platforms/prpmc750.h>
-
-#define RS_TABLE_SIZE  4
-
-/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
-#define BASE_BAUD  (PRPMC750_BASE_BAUD / 16)
-
-#ifndef SERIAL_MAGIC_KEY
-#define kernel_debugger ppc_kernel_debug
-#endif
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-#define SERIAL_PORT_DFNS \
-        { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \
-		iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \
-		iomem_reg_shift: 4, \
-		io_type: SERIAL_IO_MEM } /* ttyS0 */
-
-#endif /* __ASM_PRPMC750_SERIAL_H__ */
-#endif /* __KERNEL__ */
diff -Nru a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c
--- a/arch/ppc/platforms/prpmc800.c	2004-04-29 07:20:38 -07:00
+++ b/arch/ppc/platforms/prpmc800.c	2004-08-16 09:04:08 -07:00
@@ -309,10 +309,6 @@
 		ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	printk(KERN_INFO "Port by MontaVista Software, Inc. "
 			 "(source@mvista.com)\n");
 }
diff -Nru a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h
--- a/arch/ppc/platforms/prpmc800.h	2004-04-29 02:41:09 -07:00
+++ b/arch/ppc/platforms/prpmc800.h	2004-08-12 15:19:29 -07:00
@@ -5,12 +5,10 @@
  *
  * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
  *
- * Copyright 2001 MontaVista Software Inc.
- *
- * 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 of the  License, or (at your
- * option) any later version.
+ * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
  */
  /*
   * From Processor to PCI:
@@ -62,5 +60,23 @@
  */
 #define PRPMC800_INT_IRQ			16
 #define PRPMC800_INT_PRI			15
+
+/* UART Defines. */
+#define RS_TABLE_SIZE  4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD (PRPMC800_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* UARTS are at IRQ 16 */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\
+		iomem_base: (unsigned char *)PRPMC800_SERIAL_1,		\
+		iomem_reg_shift: 0,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
 
 #endif				/* __ASMPPC_PRPMC800_H */
diff -Nru a/arch/ppc/platforms/prpmc800_serial.h b/arch/ppc/platforms/prpmc800_serial.h
--- a/arch/ppc/platforms/prpmc800_serial.h	2003-09-12 09:26:54 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,49 +0,0 @@
-/*
- * arch/ppc/platforms/prpmc800_serial.h
- *
- * Definitions for Motorola MCG PRPMC800 cPCI board support
- *
- * Author: Dale Farnsworth	dale.farnsworth@mvista.com
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASMPPC_PRPMC800_SERIAL_H
-#define __ASMPPC_PRPMC800_SERIAL_H
-
-#include <linux/config.h>
-#include <platforms/prpmc800.h>
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE  64
-#else
-#define RS_TABLE_SIZE  4
-#endif
-
-/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
-#define BASE_BAUD (PRPMC800_BASE_BAUD / 16)
-
-#ifndef SERIAL_MAGIC_KEY
-#define kernel_debugger ppc_kernel_debug
-#endif
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-/* UARTS are at IRQ 16 */
-#define STD_SERIAL_PORT_DFNS \
-        { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\
-		iomem_base: (unsigned char *)PRPMC800_SERIAL_1,		\
-		iomem_reg_shift: 0,					\
-		io_type: SERIAL_IO_MEM },
-
-#define SERIAL_PORT_DFNS \
-        STD_SERIAL_PORT_DFNS
-
-#endif /* __ASMPPC_PRPMC800_SERIAL_H */
diff -Nru a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
--- a/arch/ppc/platforms/residual.c	2004-07-26 11:43:24 -07:00
+++ b/arch/ppc/platforms/residual.c	2004-08-16 10:43:39 -07:00
@@ -504,7 +504,7 @@
 #define did dev->DeviceId
 
 	/* make sure we have residual data first */
-	if ( res->ResidualLength == 0 )
+	if (!have_residual_data)
 		return;
 
 	printk("Residual: %ld devices\n", res->ActualNumDevices);
@@ -639,7 +639,7 @@
 #define did dev->DeviceId
 
 	/* make sure we have residual data first */
-	if ( res->ResidualLength == 0 )
+	if (!have_residual_data)
 		return;
 	printk("Residual: %ld devices\n", res->ActualNumDevices);
 	for ( i = 0;
@@ -790,7 +790,7 @@
 			 int n)
 {
 	int i;
-	if ( !res->ResidualLength ) return NULL;
+	if (!have_residual_data) return NULL;
 	for (i=0; i<res->ActualNumDevices; i++) {
 #define Dev res->Devices[i].DeviceId
 		if ( (Dev.BusId&BusMask)                                  &&
@@ -813,7 +813,7 @@
 			 int n)
 {
 	int i;
-	if ( !res->ResidualLength ) return NULL;
+	if (!have_residual_data) return NULL;
 	for (i=0; i<res->ActualNumDevices; i++) {
 #define Dev res->Devices[i].DeviceId
 		if ( (Dev.BusId&BusMask)                                  &&
@@ -827,6 +827,129 @@
 	return NULL;
 }
 
+static int __init
+residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
+{
+	int irq = -1;
+
+#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
+	if (dev->bus->number == data[16]) {
+		int i, size;
+
+		size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0));
+		for (i = 20; i < size - 4; i += 12) {
+			unsigned char pin;
+			int line_irq;
+
+			if (dev->devfn != data[i + 1])
+				continue;
+
+			pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+			if (pin) {
+				line_irq = ld_le16((unsigned short *)
+						(&data[i + 4 + 2 * (pin - 1)]));
+				irq = (line_irq == 0xffff) ? 0
+							   : line_irq & 0x7fff;
+			} else
+				irq = 0;
+
+			break;
+		}
+	}
+#undef data
+
+	return irq;
+}
+
+int __init
+residual_pcidev_irq(struct pci_dev *dev)
+{
+	int i = 0;
+	int irq = -1;
+	PPC_DEVICE *bridge;
+
+	while ((bridge = residual_find_device
+	       (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
+
+		PnP_TAG_PACKET *pkt;
+		if (bridge->AllocatedOffset) {
+			pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+					   bridge->AllocatedOffset, 3, 0);
+			if (!pkt)
+				continue;
+
+			irq = residual_scan_pcibridge(pkt, dev);
+			if (irq != -1)
+				break;
+		}
+	}
+
+	return (irq < 0) ? 0 : irq;
+}
+
+void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	PPC_DEVICE *dev;
+	int i = 0;
+	unsigned short irq_mask = 0x000; /* default to edge */
+
+	while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) {
+		PnP_TAG_PACKET *pkt;
+		unsigned short mask;
+		int size;
+		int offset = dev->AllocatedOffset;
+
+		if (!offset)
+			continue;
+
+		pkt = PnP_find_packet(res->DevicePnPHeap + offset,
+					      IRQFormat, 0);
+		if (!pkt)
+			continue;
+
+		size = tag_small_count(pkt->S1_Pack.Tag) + 1;
+		mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask);
+		if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c))
+			irq_mask |= mask;
+	}
+
+	*irq_edge_mask_lo = irq_mask & 0xff;
+	*irq_edge_mask_hi = irq_mask >> 8;
+}
+
+unsigned int __init residual_isapic_addr(void)
+{
+	PPC_DEVICE *isapic;
+	PnP_TAG_PACKET *pkt;
+	unsigned int addr;
+
+	isapic = residual_find_device(~0, NULL, SystemPeripheral,
+				      ProgrammableInterruptController,
+				      ISA_PIC, 0);
+	if (!isapic)
+		goto unknown;
+
+	pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+						isapic->AllocatedOffset, 9, 0);
+	if (!pkt)
+		goto unknown;
+
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+	/* Must be 32-bit memory address */
+	if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32)))
+		goto unknown;
+
+	/* It doesn't seem to work where length != 1 (what can I say? :-/ ) */
+	if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1)
+		goto unknown;
+
+	addr = ld_le32((unsigned int *) (p.PPCData + 4));
+#undef p
+	return addr;
+unknown:
+	return 0;
+}
+
 PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
 				unsigned packet_tag,
 				int n)
@@ -901,7 +1024,7 @@
 int __init
 proc_prep_residual_init(void)
 {
-	if (res->ResidualLength)
+	if (have_residual_data)
 		create_proc_read_entry("residual", S_IRUGO, NULL,
 					proc_prep_residual_read, NULL);
 	return 0;
diff -Nru a/arch/ppc/platforms/rpx8260.c b/arch/ppc/platforms/rpx8260.c
--- a/arch/ppc/platforms/rpx8260.c	2004-07-27 14:46:38 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,65 +0,0 @@
-/*
- * arch/ppc/platforms/rpx8260.c
- *
- * RPC EP8260 platform support
- *
- * Author: Dan Malek <dan@embeddededge.com>
- * Derived from: pq2ads_setup.c by Kumar
- *
- * Copyright 2004 Embedded Edge, LLC
- *
- * 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 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/seq_file.h>
-
-#include <asm/mpc8260.h>
-#include <asm/machdep.h>
-
-static void (*callback_setup_arch)(void);
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void m8260_init(unsigned long r3, unsigned long r4,
-	unsigned long r5, unsigned long r6, unsigned long r7);
-
-static int
-ep8260_show_cpuinfo(struct seq_file *m)
-{
-	bd_t	*binfo = (bd_t *)__res;
-
-	seq_printf(m, "vendor\t\t: RPC\n"
-		      "machine\t\t: EP8260 PPC\n"
-		      "\n"
-		      "mem size\t\t: 0x%08x\n"
-		      "console baud\t\t: %d\n"
-		      "\n",
-		      binfo->bi_memsize,
-		      binfo->bi_baudrate);
-	return 0;
-}
-
-static void __init
-ep8260_setup_arch(void)
-{
-	printk("RPC EP8260 Port\n");
-	callback_setup_arch();
-}
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
-{
-	/* Generic 8260 platform initialization */
-	m8260_init(r3, r4, r5, r6, r7);
-
-	/* Anything special for this platform */
-	ppc_md.show_cpuinfo	= ep8260_show_cpuinfo;
-
-	callback_setup_arch	= ppc_md.setup_arch;
-	ppc_md.setup_arch	= ep8260_setup_arch;
-}
diff -Nru a/arch/ppc/platforms/rpx8260.h b/arch/ppc/platforms/rpx8260.h
--- a/arch/ppc/platforms/rpx8260.h	2004-07-27 14:46:37 -07:00
+++ b/arch/ppc/platforms/rpx8260.h	2004-08-13 14:03:33 -07:00
@@ -70,5 +70,12 @@
 
 #define PHY_INTERRUPT	SIU_INT_IRQ7
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Embedded Planet"
+#define CPUINFO_MACHINE		"EP8260 PowerPC"
+
+/* Warm reset vector. */
+#define BOOTROM_RESTART_ADDR	((uint)0xfff00104)
+
 #endif /* __ASM_PLATFORMS_RPX8260_H__ */
 #endif /* __KERNEL__ */
diff -Nru a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
--- a/arch/ppc/platforms/sandpoint.c	2004-07-01 22:23:46 -07:00
+++ b/arch/ppc/platforms/sandpoint.c	2004-08-16 09:04:08 -07:00
@@ -303,10 +303,6 @@
 	/* Lookup PCI host bridges */
 	sandpoint_find_bridges();
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
 	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
 
diff -Nru a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c
--- a/arch/ppc/platforms/sbc82xx.c	2004-08-04 04:55:48 -07:00
+++ b/arch/ppc/platforms/sbc82xx.c	2004-08-25 07:50:20 -07:00
@@ -16,10 +16,10 @@
  */
 
 #include <linux/config.h>
-#include <linux/seq_file.h>
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/init.h>
 #include <linux/pci.h>
 
 #include <asm/mpc8260.h>
@@ -29,39 +29,12 @@
 #include <asm/immap_cpm2.h>
 #include <asm/pci.h>
 
-static void (*callback_setup_arch)(void);
 static void (*callback_init_IRQ)(void);
 
 extern unsigned char __res[sizeof(bd_t)];
 
-extern void m8260_init(unsigned long r3, unsigned long r4,
-	unsigned long r5, unsigned long r6, unsigned long r7);
-
 extern void (*late_time_init)(void);
 
-static int
-sbc82xx_show_cpuinfo(struct seq_file *m)
-{
-	bd_t	*binfo = (bd_t *)__res;
-
-	seq_printf(m, "vendor\t\t: Wind River\n"
-		      "machine\t\t: SBC PowerQUICC II\n"
-		      "\n"
-		      "mem size\t\t: 0x%08lx\n"
-		      "console baud\t\t: %ld\n"
-		      "\n",
-		      binfo->bi_memsize,
-		      binfo->bi_baudrate);
-	return 0;
-}
-
-static void __init
-sbc82xx_setup_arch(void)
-{
-	printk("SBC PowerQUICC II Port\n");
-	callback_setup_arch();
-}
-
 #ifdef CONFIG_GEN_RTC
 TODC_ALLOC();
 
@@ -237,7 +210,6 @@
 	return PCI_IRQ_TABLE_LOOKUP;
 }
 
-
 static void __devinit quirk_sbc8260_cardbus(struct pci_dev *pdev)
 {
 	uint32_t ctrl;
@@ -259,23 +231,15 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, quirk_sbc8260_cardbus);
 
 void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
+m82xx_board_init(void)
 {
-	/* Generic 8260 platform initialization */
-	m8260_init(r3, r4, r5, r6, r7);
-
 	/* u-boot may be using one of the FCC Ethernet devices.
 	   Use the MAC address to the SCC. */
 	__res[offsetof(bd_t, bi_enetaddr[5])] &= ~3;
 
 	/* Anything special for this platform */
-	ppc_md.show_cpuinfo	= sbc82xx_show_cpuinfo;
-
-	callback_setup_arch	= ppc_md.setup_arch;
 	callback_init_IRQ	= ppc_md.init_IRQ;
 
-	ppc_md.setup_arch	= sbc82xx_setup_arch;
 	ppc_md.init_IRQ		= sbc82xx_init_IRQ;
 	ppc_md.pci_map_irq	= sbc82xx_pci_map_irq;
 #ifdef CONFIG_GEN_RTC
diff -Nru a/arch/ppc/platforms/sbc82xx.h b/arch/ppc/platforms/sbc82xx.h
--- a/arch/ppc/platforms/sbc82xx.h	2004-06-16 16:01:26 -07:00
+++ b/arch/ppc/platforms/sbc82xx.h	2004-08-13 14:03:33 -07:00
@@ -18,6 +18,10 @@
 #define SBC82xx_MACADDR_NVRAM_FCC2	0x220000d5	/* JP7A */
 #define SBC82xx_MACADDR_NVRAM_FCC3	0x220000db	/* JP7B */
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Wind River"
+#define CPUINFO_MACHINE		"SBC PowerQUICC II"
+
 #define BOOTROM_RESTART_ADDR      ((uint)0x40000104)
 
 #define SBC82xx_PC_IRQA (NR_SIU_INTS+0)
diff -Nru a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c
--- a/arch/ppc/platforms/spruce.c	2004-02-18 12:41:47 -08:00
+++ b/arch/ppc/platforms/spruce.c	2004-08-16 09:04:08 -07:00
@@ -228,11 +228,6 @@
 		ROOT_DEV = Root_SDA1;
 #endif
 
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
-#endif
-
-
 	/* Identify the system */
 	printk(KERN_INFO "System Identification: IBM Spruce\n");
 	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
diff -Nru a/arch/ppc/platforms/tqm8260.h b/arch/ppc/platforms/tqm8260.h
--- a/arch/ppc/platforms/tqm8260.h	2004-06-16 10:56:13 -07:00
+++ b/arch/ppc/platforms/tqm8260.h	2004-08-13 14:03:33 -07:00
@@ -14,6 +14,10 @@
 #define CPM_MAP_ADDR		((uint)0xFFF00000)
 #define PHY_INTERRUPT		25
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"IN2 Systems"
+#define CPUINFO_MACHINE		"TQM8260 PowerPC"
+
 #define BOOTROM_RESTART_ADDR	((uint)0x40000104)
 
 #endif	/* __TQM8260_PLATFORM */
diff -Nru a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c
--- a/arch/ppc/platforms/tqm8260_setup.c	2004-06-16 10:56:13 -07:00
+++ b/arch/ppc/platforms/tqm8260_setup.c	2004-08-13 16:33:54 -07:00
@@ -14,33 +14,12 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
-#include <linux/seq_file.h>
+#include <linux/init.h>
 
 #include <asm/immap_cpm2.h>
 #include <asm/mpc8260.h>
 #include <asm/machdep.h>
 
-static void (*callback_setup_arch)(void);
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void m8260_init(unsigned long r3, unsigned long r4,
-	unsigned long r5, unsigned long r6, unsigned long r7);
-
-static int
-tqm8260_show_cpuinfo(struct seq_file *m)
-{
-	bd_t	*binfo = (bd_t *)__res;
-
-	seq_printf(m, "vendor\t\t: IN2 Systems\n"
-		      "machine\t\t: TQM8260 PowerPC\n"
-		      "mem size\t\t: 0x%08x\n"
-		      "\n",
-		      binfo->bi_memsize);
-	return 0;
-}
-
 static int
 tqm8260_set_rtc_time(unsigned long time)
 {
@@ -56,24 +35,10 @@
 	return ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt;
 }
 
-static void __init
-tqm8260_setup_arch(void)
-{
-	printk("IN2 Systems TQM8260 port\n");
-	callback_setup_arch();
-}
-
 void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
+m82xx_board_init(void)
 {
-	/* Generic 8260 platform initialization */
-	m8260_init(r3, r4, r5, r6, r7);
-
 	/* Anything special for this platform */
-	ppc_md.show_cpuinfo	= tqm8260_show_cpuinfo;
 	ppc_md.set_rtc_time	= tqm8260_set_rtc_time;
 	ppc_md.get_rtc_time	= tqm8260_get_rtc_time;
-
-	callback_setup_arch	= ppc_md.setup_arch;
-	ppc_md.setup_arch	= tqm8260_setup_arch;
+}
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile	2004-08-07 11:05:39 -07:00
+++ b/arch/ppc/syslib/Makefile	2004-08-16 08:56:56 -07:00
@@ -5,6 +5,8 @@
 CFLAGS_prom_init.o      += -fPIC
 CFLAGS_btext.o          += -fPIC
 
+wdt-mpc8xx-$(CONFIG_8xx_WDT)	+= m8xx_wdt.o
+
 obj-$(CONFIG_PPCBUG_NVRAM)	+= prep_nvram.o
 obj-$(CONFIG_PPC_OCP)		+= ocp.o
 obj-$(CONFIG_IBM_OCP)		+= ibm_ocp.o
@@ -22,7 +24,7 @@
 obj-$(CONFIG_PCI)		+= indirect_pci.o pci_auto.o ppc405_pci.o
 endif
 endif
-obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o
+obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y)
 ifeq ($(CONFIG_8xx),y)
 obj-$(CONFIG_PCI)		+= qspan_pci.o i8259.o
 endif
diff -Nru a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
--- a/arch/ppc/syslib/cpm2_pic.c	2004-06-16 10:56:13 -07:00
+++ b/arch/ppc/syslib/cpm2_pic.c	2004-08-13 16:23:50 -07:00
@@ -1,12 +1,3 @@
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <asm/irq.h>
-#include <asm/immap_cpm2.h>
-#include <asm/mpc8260.h>
-#include "cpm2_pic.h"
-
 /* The CPM2 internal interrupt controller.  It is usually
  * the only interrupt controller.
  * There are two 32-bit registers (high/low) for up to 64
@@ -18,6 +9,18 @@
  * We create two tables, indexed by vector number, to indicate
  * which register to use and which bit in the register to use.
  */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+
+#include "cpm2_pic.h"
+
 static	u_char	irq_to_siureg[] = {
 	1, 1, 1, 1, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 1, 1, 1,
@@ -123,9 +126,5 @@
 
 	if (irq == 0)
 		return(-1);
-#if 0
-        irq += ppc8260_pic.irq_offset;
-#endif
 	return irq;
 }
-
diff -Nru a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h
--- a/arch/ppc/syslib/cpm2_pic.h	2004-06-16 10:56:13 -07:00
+++ b/arch/ppc/syslib/cpm2_pic.h	2004-08-13 16:23:50 -07:00
@@ -1,13 +1,7 @@
 #ifndef _PPC_KERNEL_CPM2_H
 #define _PPC_KERNEL_CPM2_H
 
-#include <linux/irq.h>
-
 extern struct hw_interrupt_type cpm2_pic;
-
-void cpm2_pic_init(void);
-void cpm2_do_IRQ(struct pt_regs *regs,
-                 int            cpu);
-int cpm2_get_irq(struct pt_regs *regs);
+extern int cpm2_get_irq(struct pt_regs *regs);
 
 #endif /* _PPC_KERNEL_CPM2_H */
diff -Nru a/arch/ppc/syslib/hawk_common.c b/arch/ppc/syslib/hawk_common.c
--- a/arch/ppc/syslib/hawk_common.c	2004-03-31 15:49:32 -08:00
+++ b/arch/ppc/syslib/hawk_common.c	2004-08-12 16:44:46 -07:00
@@ -285,3 +285,35 @@
 
 	return total;
 }
+
+int __init
+hawk_mpic_init(unsigned int pci_mem_offset)
+{
+	unsigned short	devid;
+	unsigned int	pci_membase;
+
+	/* Check the first PCI device to see if it is a Raven or Hawk. */
+	early_read_config_word(0, 0, 0, PCI_DEVICE_ID, &devid);
+
+	switch (devid) {
+	case PCI_DEVICE_ID_MOTOROLA_RAVEN:
+	case PCI_DEVICE_ID_MOTOROLA_HAWK:
+		break;
+	default:
+		OpenPIC_Addr = NULL;
+		return 1;
+	}
+
+	/* Read the memory base register. */
+	early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+	if (pci_membase == 0) {
+		OpenPIC_Addr = NULL;
+		return 1;
+	}
+
+	/* Map the MPIC registers to virtual memory. */
+	OpenPIC_Addr = ioremap(pci_membase + pci_mem_offset, 0x22000);
+
+	return 0;
+}
diff -Nru a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h
--- a/arch/ppc/syslib/m8260_pci.h	2004-06-17 05:57:15 -07:00
+++ b/arch/ppc/syslib/m8260_pci.h	2004-08-23 11:08:39 -07:00
@@ -66,6 +66,7 @@
 #endif
 
 #ifdef CONFIG_8260_PCI9
+struct pci_controller;
 extern void setup_m8260_indirect_pci(struct pci_controller* hose,
 				     u32 cfg_addr, u32 cfg_data);
 #else
diff -Nru a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
--- a/arch/ppc/syslib/m8260_setup.c	2004-06-17 05:57:15 -07:00
+++ b/arch/ppc/syslib/m8260_setup.c	2004-08-24 08:31:20 -07:00
@@ -1,5 +1,5 @@
 /*
- *  arch/ppc/kernel/setup.c
+ *  arch/ppc/syslib/m8260_setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
  *  Adapted from 'alpha' version by Gary Thomas
@@ -8,36 +8,20 @@
  *  Further modified for generic 8xx and 8260 by Dan.
  */
 
-/*
- * bootup setup stuff..
- */
-
 #include <linux/config.h>
-#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
 #include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/initrd.h>
-#include <linux/ioport.h>
-#include <linux/ide.h>
 #include <linux/seq_file.h>
+#include <linux/irq.h>
 
 #include <asm/mmu.h>
-#include <asm/residual.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/ide.h>
 #include <asm/mpc8260.h>
 #include <asm/immap_cpm2.h>
 #include <asm/machdep.h>
@@ -46,10 +30,6 @@
 
 #include "cpm2_pic.h"
 
-static int m8260_set_rtc_time(unsigned long time);
-static unsigned long m8260_get_rtc_time(void);
-static void m8260_calibrate_decr(void);
-
 unsigned char __res[sizeof(bd_t)];
 
 extern void cpm2_reset(void);
@@ -59,8 +39,10 @@
 static void __init
 m8260_setup_arch(void)
 {
-	/* Reset the Communication Processor Module.
-	*/
+	/* Print out Vendor and Machine info. */
+	printk(KERN_INFO "%s %s port\n", CPUINFO_VENDOR, CPUINFO_MACHINE);
+
+	/* Reset the Communication Processor Module. */
 	cpm2_reset();
 #ifdef CONFIG_8260_PCI9
 	/* Initialise IDMA for PCI erratum workaround */
@@ -69,6 +51,10 @@
 #ifdef CONFIG_PCI_8260
 	m8260_find_bridges();
 #endif
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+#endif
 }
 
 /* The decrementer counts at the system (internal) clock frequency
@@ -77,7 +63,7 @@
 static void __init
 m8260_calibrate_decr(void)
 {
-	bd_t	*binfo = (bd_t *)__res;
+	bd_t *binfo = (bd_t *)__res;
 	int freq, divisor;
 
 	freq = binfo->bi_busfreq;
@@ -145,18 +131,22 @@
 }
 
 static int
-m8260_show_percpuinfo(struct seq_file *m, int i)
+m8260_show_cpuinfo(struct seq_file *m)
 {
-	bd_t	*bp;
-
-	bp = (bd_t *)__res;
+	bd_t *bp = (bd_t *)__res;
 
-	seq_printf(m, "core clock\t: %ld MHz\n"
-		   "CPM  clock\t: %ld MHz\n"
-		   "bus  clock\t: %ld MHz\n",
-		   bp->bi_intfreq / 1000000,
-		   bp->bi_cpmfreq / 1000000,
-		   bp->bi_busfreq / 1000000);
+	seq_printf(m, "vendor\t\t: %s\n"
+		   "machine\t\t: %s\n"
+		   "\n"
+		   "mem size\t\t: 0x%08x\n"
+		   "console baud\t\t: %d\n"
+		   "\n"
+		   "core clock\t: %u MHz\n"
+		   "CPM  clock\t: %u MHz\n"
+		   "bus  clock\t: %u MHz\n",
+		   CPUINFO_VENDOR, CPUINFO_MACHINE, bp->bi_memsize,
+		   bp->bi_baudrate, bp->bi_intfreq / 1000000,
+		   bp->bi_cpmfreq / 1000000, bp->bi_busfreq / 1000000);
 	return 0;
 }
 
@@ -170,7 +160,6 @@
 m8260_init_IRQ(void)
 {
 	int i;
-	void cpm_interrupt_init(void);
 
         for ( i = 0 ; i < NR_SIU_INTS ; i++ )
                 irq_desc[i].handler = &cpm2_pic;
@@ -190,10 +179,7 @@
 static unsigned long __init
 m8260_find_end_of_memory(void)
 {
-	bd_t	*binfo;
-	extern unsigned char __res[];
-
-	binfo = (bd_t *)__res;
+	bd_t *binfo = (bd_t *)__res;
 
 	return binfo->bi_memsize;
 }
@@ -216,6 +202,12 @@
 	io_block_mapping(IO_VIRT_ADDR, IO_PHYS_ADDR, 0x10000000, _PAGE_IO);
 }
 
+/* Place-holder for board-specific init */
+void __attribute__ ((weak)) __init
+m82xx_board_init(void)
+{
+}
+
 /* Inputs:
  *   r3 - Optional pointer to a board information structure.
  *   r4 - Optional pointer to the physical starting address of the init RAM
@@ -228,7 +220,7 @@
  *        command-line parameters.
  */
 void __init
-m8260_init(unsigned long r3, unsigned long r4, unsigned long r5,
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	      unsigned long r6, unsigned long r7)
 {
 	parse_bootinfo(find_bootinfo());
@@ -249,18 +241,18 @@
 		strcpy(cmd_line, (char *)(r6+KERNELBASE));
 	}
 
+	/* Call back for board-specific settings. */
+	m82xx_board_init();
+
 	ppc_md.setup_arch		= m8260_setup_arch;
-	ppc_md.show_percpuinfo		= m8260_show_percpuinfo;
-	ppc_md.irq_canonicalize	= NULL;
+	ppc_md.show_cpuinfo		= m8260_show_cpuinfo;
 	ppc_md.init_IRQ			= m8260_init_IRQ;
 	ppc_md.get_irq			= cpm2_get_irq;
-	ppc_md.init			= NULL;
 
 	ppc_md.restart			= m8260_restart;
 	ppc_md.power_off		= m8260_power_off;
 	ppc_md.halt			= m8260_halt;
 
-	ppc_md.time_init		= NULL;
 	ppc_md.set_rtc_time		= m8260_set_rtc_time;
 	ppc_md.get_rtc_time		= m8260_get_rtc_time;
 	ppc_md.calibrate_decr		= m8260_calibrate_decr;
diff -Nru a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
--- a/arch/ppc/syslib/m8xx_setup.c	2004-05-10 04:25:37 -07:00
+++ b/arch/ppc/syslib/m8xx_setup.c	2004-08-03 11:04:21 -07:00
@@ -60,6 +60,11 @@
 extern void m8xx_cpm_reset(uint);
 extern void rpxfb_alloc_pages(void);
 
+void __attribute__ ((weak))
+board_init(void)
+{
+}
+
 void __init
 m8xx_setup_arch(void)
 {
@@ -102,6 +107,7 @@
 	}
 #endif
 #endif
+	board_init();
 }
 
 void
diff -Nru a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/m8xx_wdt.c	2004-08-03 11:13:56 -07:00
@@ -0,0 +1,99 @@
+/*
+ * m8xx_wdt.c - MPC8xx watchdog driver
+ *
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/8xx_immap.h>
+#include <syslib/m8xx_wdt.h>
+
+static int wdt_timeout;
+
+void m8xx_wdt_reset(void)
+{
+	volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+	imap->im_siu_conf.sc_swsr = 0x556c;	/* write magic1 */
+	imap->im_siu_conf.sc_swsr = 0xaa39;	/* write magic2 */
+}
+
+static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+	m8xx_wdt_reset();
+
+	imap->im_sit.sit_piscr |= PISCR_PS;	/* clear irq */
+
+	return IRQ_HANDLED;
+}
+
+void __init m8xx_wdt_handler_install(bd_t * binfo)
+{
+	volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+	u32 pitc;
+	u32 sypcr;
+	u32 pitrtclk;
+
+	sypcr = imap->im_siu_conf.sc_sypcr;
+
+	if (!(sypcr & 0x04)) {
+		printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n",
+		       sypcr);
+		return;
+	}
+
+	m8xx_wdt_reset();
+
+	printk(KERN_NOTICE
+	       "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n",
+	       (sypcr >> 16), sypcr & 0x01);
+
+	wdt_timeout = (sypcr >> 16) & 0xFFFF;
+
+	if (!wdt_timeout)
+		wdt_timeout = 0xFFFF;
+
+	if (sypcr & 0x01)
+		wdt_timeout *= 2048;
+
+	/*
+	 * Fire trigger if half of the wdt ticked down 
+	 */
+
+	if (imap->im_sit.sit_rtcsc & RTCSC_38K)
+		pitrtclk = 9600;
+	else
+		pitrtclk = 8192;
+
+	if ((wdt_timeout) > (UINT_MAX / pitrtclk))
+		pitc = wdt_timeout / binfo->bi_intfreq * pitrtclk / 2;
+	else
+		pitc = pitrtclk * wdt_timeout / binfo->bi_intfreq / 2;
+
+	imap->im_sit.sit_pitc = pitc << 16;
+	imap->im_sit.sit_piscr =
+	    (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE;
+
+	if (request_irq(PIT_INTERRUPT, m8xx_wdt_interrupt, 0, "watchdog", NULL))
+		panic("m8xx_wdt: could not allocate watchdog irq!");
+
+	printk(KERN_NOTICE
+	       "m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc);
+
+	wdt_timeout /= binfo->bi_intfreq;
+}
+
+int m8xx_wdt_get_timeout(void)
+{
+	return wdt_timeout;
+}
diff -Nru a/arch/ppc/syslib/m8xx_wdt.h b/arch/ppc/syslib/m8xx_wdt.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/m8xx_wdt.h	2004-08-03 11:13:56 -07:00
@@ -0,0 +1,16 @@
+/*
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef _PPC_SYSLIB_M8XX_WDT_H
+#define _PPC_SYSLIB_M8XX_WDT_H
+
+extern void m8xx_wdt_handler_install(bd_t * binfo);
+extern int m8xx_wdt_get_timeout(void);
+extern void m8xx_wdt_reset(void);
+
+#endif				/* _PPC_SYSLIB_M8XX_WDT_H */
diff -Nru a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
--- a/arch/ppc/syslib/ppc4xx_setup.c	2004-02-13 07:24:54 -08:00
+++ b/arch/ppc/syslib/ppc4xx_setup.c	2004-08-16 09:04:08 -07:00
@@ -61,10 +61,6 @@
 #ifdef CONFIG_PCI
 	ppc4xx_find_bridges();
 #endif
-
-#if defined(CONFIG_FB)
-	conswitchp = &dummy_con;
-#endif
 }
 
 /*
diff -Nru a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
--- a/arch/ppc/syslib/ppc85xx_setup.c	2004-08-02 01:00:42 -07:00
+++ b/arch/ppc/syslib/ppc85xx_setup.c	2004-08-27 00:02:36 -07:00
@@ -277,7 +277,7 @@
 	hose_a->io_space.start = MPC85XX_PCI1_LOWER_IO;
 	hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO;
 	hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE;
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
 	isa_io_base =
 		(unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
 					MPC85XX_PCI1_IO_SIZE +
@@ -304,7 +304,7 @@
 
 	hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
 
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
 	hose_b = pcibios_alloc_controller();
 
 	if (!hose_b)
diff -Nru a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
--- a/arch/ppc64/Kconfig.debug	2004-08-15 12:45:32 -07:00
+++ b/arch/ppc64/Kconfig.debug	2004-08-24 02:08:11 -07:00
@@ -54,4 +54,16 @@
 
 	  If in doubt, say N.
 
+config SCHEDSTATS
+	bool "Collect scheduler statistics"
+	depends on DEBUG_KERNEL && PROC_FS
+	help
+	  If you say Y here, additional code will be inserted into the
+	  scheduler and related routines to collect statistics about
+	  scheduler behavior and provide them in /proc/schedstat.  These
+	  stats may be useful for both tuning and debugging the scheduler
+	  If you aren't debugging the scheduler or trying to tune a specific
+	  application, you can say N to avoid the very slight overhead
+	  this adds.
+
 endmenu
diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
--- a/arch/ppc64/kernel/asm-offsets.c	2004-08-23 01:14:36 -07:00
+++ b/arch/ppc64/kernel/asm-offsets.c	2004-08-26 23:30:32 -07:00
@@ -98,11 +98,6 @@
 	DEFINE(PACAHTLBSEGS, offsetof(struct paca_struct, context.htlb_segs));
 #endif /* CONFIG_HUGETLB_PAGE */
 	DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr));
-	DEFINE(PACAPROFENABLED, offsetof(struct paca_struct, prof_enabled));
-	DEFINE(PACAPROFLEN, offsetof(struct paca_struct, prof_len));
-	DEFINE(PACAPROFSHIFT, offsetof(struct paca_struct, prof_shift));
-	DEFINE(PACAPROFBUFFER, offsetof(struct paca_struct, prof_buffer));
-	DEFINE(PACAPROFSTEXT, offsetof(struct paca_struct, prof_stext));
         DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
         DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
         DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
--- a/arch/ppc64/kernel/head.S	2004-08-23 01:14:41 -07:00
+++ b/arch/ppc64/kernel/head.S	2004-08-26 23:30:32 -07:00
@@ -322,36 +322,11 @@
 	HMT_MEDIUM;							\
 	mtspr	SPRG1,r13;		/* save r13 */			\
 	EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN);				\
-	lbz	r10,PACAPROFENABLED(r13);				\
-	cmpwi	r10,0;							\
-	bne-	label##_Iseries_profile;				\
-label##_Iseries_prof_ret:						\
 	lbz	r10,PACAPROCENABLED(r13);				\
 	cmpwi	0,r10,0;						\
 	beq-	label##_Iseries_masked;					\
 	EXCEPTION_PROLOG_ISERIES_2;					\
 	b	label##_common;						\
-label##_Iseries_profile:						\
-	ld	r12,PACALPPACA+LPPACASRR1(r13);				\
-	andi.	r12,r12,MSR_PR;		/* Test if in kernel */		\
-	bne	label##_Iseries_prof_ret;				\
-	ld	r11,PACALPPACA+LPPACASRR0(r13);				\
-	ld	r12,PACAPROFSTEXT(r13);	/* _stext */			\
-	subf	r11,r12,r11;		/* offset into kernel */	\
-	lwz	r12,PACAPROFSHIFT(r13);					\
-	srd	r11,r11,r12;						\
-	lwz	r12,PACAPROFLEN(r13);	/* profile table length - 1 */	\
-	cmpd	r11,r12;		/* off end? */			\
-	ble	1f;							\
-	mr	r11,r12;		/* force into last entry */	\
-1:	sldi	r11,r11,2;		/* convert to offset */		\
-	ld	r12,PACAPROFBUFFER(r13);/* profile buffer */		\
-	add	r12,r12,r11;						\
-2:	lwarx	r11,0,r12;		/* atomically increment */	\
-	addi	r11,r11,1;						\
-	stwcx.	r11,0,r12;						\
-	bne-	2b;							\
-	b	label##_Iseries_prof_ret
 
 #ifdef DO_SOFT_DISABLE
 #define DISABLE_INTS				\
@@ -1037,6 +1012,9 @@
 	 * interrupts if necessary.
 	 */
 	beq	.ret_from_except_lite
+	/* For a hash failure, we don't bother re-enabling interrupts */
+	ble-	12f
+
 	/*
 	 * hash_page couldn't handle it, set soft interrupt enable back
 	 * to what it was before the trap.  Note that .local_irq_restore
@@ -1047,6 +1025,8 @@
 	b	11f
 #else
 	beq	fast_exception_return   /* Return from exception on success */
+	ble-	12f			/* Failure return from hash_page */
+
 	/* fall through */
 #endif
 
@@ -1064,6 +1044,15 @@
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	lwz	r4,_DAR(r1)
 	bl	.bad_page_fault
+	b	.ret_from_except
+
+/* We have a page fault that hash_page could handle but HV refused
+ * the PTE insertion
+ */
+12:	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	lwz	r4,_DAR(r1)
+	bl	.low_hash_fault
 	b	.ret_from_except
 
 	/* here we have a segment miss */
diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
--- a/arch/ppc64/kernel/iSeries_setup.c	2004-07-01 22:23:46 -07:00
+++ b/arch/ppc64/kernel/iSeries_setup.c	2004-08-26 23:30:32 -07:00
@@ -36,6 +36,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/cputable.h>
+#include <asm/sections.h>
 
 #include <asm/time.h>
 #include "iSeries_setup.h"
@@ -54,17 +55,12 @@
 #include <asm/iSeries/mf.h>
 
 /* Function Prototypes */
-extern void abort(void);
 extern void ppcdbg_initialize(void);
-extern void iSeries_pcibios_init(void);
 extern void tce_init_iSeries(void);
 
 static void build_iSeries_Memory_Map(void);
 static void setup_iSeries_cache_sizes(void);
 static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
-extern void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa,
-			     pte_t *ptep, unsigned hpteflags, unsigned bolted);
-static void iSeries_setup_dprofile(void);
 extern void iSeries_setup_arch(void);
 extern void iSeries_pci_final_fixup(void);
 
@@ -77,16 +73,10 @@
 static unsigned long tbFreqMhz;
 static unsigned long tbFreqMhzHundreths;
 
-unsigned long dprof_shift;
-unsigned long dprof_len;
-unsigned int *dprof_buffer;
-
 int piranha_simulator;
 
 int boot_cpuid;
 
-extern char _end[];
-
 extern int rd_size;		/* Defined in drivers/block/rd.c */
 extern unsigned long klimit;
 extern unsigned long embedded_sysmap_start;
@@ -366,30 +356,6 @@
 	}
 	*p = 0;
 
-        if (strstr(cmd_line, "dprofile=")) {
-                for (q = cmd_line; (p = strstr(q, "dprofile=")) != 0; ) {
-			unsigned long size, new_klimit;
-
-                        q = p + 9;
-                        if ((p > cmd_line) && (p[-1] != ' '))
-                                continue;
-                        dprof_shift = simple_strtoul(q, &q, 0);
-			dprof_len = (unsigned long)_etext -
-				(unsigned long)_stext;
-			dprof_len >>= dprof_shift;
-			size = ((dprof_len * sizeof(unsigned int)) +
-					(PAGE_SIZE-1)) & PAGE_MASK;
-			dprof_buffer = (unsigned int *)((klimit +
-						(PAGE_SIZE-1)) & PAGE_MASK);
-			new_klimit = ((unsigned long)dprof_buffer) + size;
-			lmb_reserve(__pa(klimit), (new_klimit-klimit));
-			klimit = new_klimit;
-			memset(dprof_buffer, 0, size);
-                }
-        }
-
-	iSeries_setup_dprofile();
-
 	mf_init();
 	mf_initialized = 1;
 	mb();
@@ -834,22 +800,6 @@
 		if (embedded_sysmap_end)
 			klimit = KERNELBASE + ((embedded_sysmap_end + 4095) &
 					0xfffffffffffff000);
-	}
-}
-
-static void iSeries_setup_dprofile(void)
-{
-	if (dprof_buffer) {
-		unsigned i;
-
-		for (i = 0; i < NR_CPUS; ++i) {
-			paca[i].prof_shift = dprof_shift;
-			paca[i].prof_len = dprof_len - 1;
-			paca[i].prof_buffer = dprof_buffer;
-			paca[i].prof_stext = (unsigned *)_stext;
-			mb();
-			paca[i].prof_enabled = 1;
-		}
 	}
 }
 
diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
--- a/arch/ppc64/kernel/irq.c	2004-08-23 01:14:36 -07:00
+++ b/arch/ppc64/kernel/irq.c	2004-08-26 23:30:30 -07:00
@@ -758,44 +758,6 @@
 	return ret;
 }
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data;
-	unsigned long full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-
-#ifdef CONFIG_PPC_ISERIES
-	{
-		unsigned i;
-		for (i=0; i<NR_CPUS; ++i) {
-			if ( paca[i].prof_buffer && cpu_isset(i, new_value) )
-				paca[i].prof_enabled = 1;
-			else
-				paca[i].prof_enabled = 0;
-		}
-	}
-#endif
-
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -825,26 +787,15 @@
 	smp_affinity_entry[irq] = entry;
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", NULL);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-		return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	2004-06-16 22:46:06 -07:00
+++ b/arch/ppc64/kernel/misc.S	2004-08-26 23:30:32 -07:00
@@ -454,12 +454,6 @@
 	sync
 	blr	
 
-_GLOBAL(abs)
-	cmpi	0,r3,0
-	bge	10f
-	neg	r3,r3
-10:	blr
-
 _GLOBAL(_get_PVR)
 	mfspr	r3,PVR
 	blr
diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
--- a/arch/ppc64/kernel/pSeries_lpar.c	2004-07-24 21:51:52 -07:00
+++ b/arch/ppc64/kernel/pSeries_lpar.c	2004-08-24 00:29:18 -07:00
@@ -377,7 +377,7 @@
 	lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, lhpte.dw0.dword0,
 			      lhpte.dw1.dword1, &slot, &dummy0, &dummy1);
 
-	if (lpar_rc == H_PTEG_Full)
+	if (unlikely(lpar_rc == H_PTEG_Full))
 		return -1;
 
 	/*
@@ -385,7 +385,7 @@
 	 * will fail. However we must catch the failure in hash_page
 	 * or we will loop forever, so return -2 in this case.
 	 */
-	if (lpar_rc != H_Success)
+	if (unlikely(lpar_rc != H_Success))
 		return -2;
 
 	/* Because of iSeries, we have to pass down the secondary
@@ -415,9 +415,7 @@
 		if (lpar_rc == H_Success)
 			return i;
 
-		if (lpar_rc != H_Not_Found)
-			panic("Bad return code from pte remove rc = %lx\n",
-			      lpar_rc);
+		BUG_ON(lpar_rc != H_Not_Found);
 
 		slot_offset++;
 		slot_offset &= 0x7;
@@ -447,8 +445,7 @@
 	if (lpar_rc == H_Not_Found)
 		return -1;
 
-	if (lpar_rc != H_Success)
-		panic("bad return code from pte protect rc = %lx\n", lpar_rc);
+	BUG_ON(lpar_rc != H_Success);
 
 	return 0;
 }
@@ -467,8 +464,7 @@
 	
 	lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
 
-	if (lpar_rc != H_Success)
-		panic("Error on pte read in get_hpte0 rc = %lx\n", lpar_rc);
+	BUG_ON(lpar_rc != H_Success);
 
 	return dword0;
 }
@@ -519,15 +515,12 @@
 	vpn = va >> PAGE_SHIFT;
 
 	slot = pSeries_lpar_hpte_find(vpn);
-	if (slot == -1)
-		panic("updateboltedpp: Could not find page to bolt\n");
+	BUG_ON(slot == -1);
 
 	flags = newpp & 3;
 	lpar_rc = plpar_pte_protect(flags, slot, 0);
 
-	if (lpar_rc != H_Success)
-		panic("Bad return code from pte bolted protect rc = %lx\n",
-		      lpar_rc); 
+	BUG_ON(lpar_rc != H_Success);
 }
 
 static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
@@ -546,8 +539,7 @@
 	if (lpar_rc == H_Not_Found)
 		return;
 
-	if (lpar_rc != H_Success)
-		panic("Bad return code from invalidate rc = %lx\n", lpar_rc);
+	BUG_ON(lpar_rc != H_Success);
 }
 
 /*
diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
--- a/arch/ppc64/kernel/process.c	2004-06-16 22:46:06 -07:00
+++ b/arch/ppc64/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -458,7 +458,7 @@
 		}
 	}
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0,
+	return do_fork(clone_flags, p2, regs, 0,
 		    (int __user *)parent_tidptr, (int __user *)child_tidptr);
 }
 
diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
--- a/arch/ppc64/kernel/signal.c	2004-08-23 01:14:41 -07:00
+++ b/arch/ppc64/kernel/signal.c	2004-08-25 10:13:41 -07:00
@@ -459,17 +459,13 @@
 	/* Set up Signal Frame */
 	setup_rt_frame(sig, ka, info, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
 	}
-	return;
 }
 
 static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
@@ -512,6 +508,7 @@
 {
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * If the current thread is 32 bit - invoke the
@@ -523,14 +520,12 @@
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
-		struct k_sigaction *ka = &current->sighand->action[signr-1];
-
 		/* Whee!  Actually deliver the signal.  */
 		if (TRAP(regs) == 0x0C00)
-			syscall_restart(regs, ka);
-		handle_signal(signr, ka, &info, oldset, regs);
+			syscall_restart(regs, &ka);
+		handle_signal(signr, &ka, &info, oldset, regs);
 		return 1;
 	}
 
diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	2004-07-05 03:27:10 -07:00
+++ b/arch/ppc64/kernel/signal32.c	2004-08-25 10:13:41 -07:00
@@ -699,9 +699,7 @@
 	printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
 	       regs, frame, newsp);
 #endif
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig)
@@ -864,9 +862,7 @@
 	printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n",
 	       regs, frame, *newspp);
 #endif
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -928,18 +924,16 @@
 int do_signal32(sigset_t *oldset, struct pt_regs *regs)
 {
 	siginfo_t info;
-	struct k_sigaction *ka;
 	unsigned int frame, newsp;
 	int signr, ret;
+	struct k_sigaction ka;
 
 	if (!oldset)
 		oldset = &current->blocked;
 
 	newsp = frame = 0;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
-
-	ka = (signr == 0)? NULL: &current->sighand->action[signr-1];
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
 	if (TRAP(regs) == 0x0C00		/* System Call! */
 	    && regs->ccr & 0x10000000		/* error signalled */
@@ -950,7 +944,7 @@
 		if (signr > 0
 		    && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
 			|| (ret == ERESTARTSYS
-			    && !(ka->sa.sa_flags & SA_RESTART)))) {
+			    && !(ka.sa.sa_flags & SA_RESTART)))) {
 			/* make the system call return an EINTR error */
 			regs->result = -EINTR;
 			regs->gpr[3] = EINTR;
@@ -969,7 +963,7 @@
 	if (signr == 0)
 		return 0;		/* no signals delivered */
 
-	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
+	if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
 	    && (!on_sig_stack(regs->gpr[1])))
 		newsp = (current->sas_ss_sp + current->sas_ss_size);
 	else
@@ -977,17 +971,15 @@
 	newsp &= ~0xfUL;
 
 	/* Whee!  Actually deliver the signal.  */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		handle_rt_signal32(signr, ka, &info, oldset, regs, newsp);
+	if (ka.sa.sa_flags & SA_SIGINFO)
+		handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
 	else
-		handle_signal32(signr, ka, &info, oldset, regs, newsp);
-
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
+		handle_signal32(signr, &ka, &info, oldset, regs, newsp);
 
-	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+	if (!(ka.sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigorsets(&current->blocked, &current->blocked,
+			  &ka.sa.sa_mask);
 		sigaddset(&current->blocked, signr);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
--- a/arch/ppc64/kernel/smp.c	2004-08-23 01:14:42 -07:00
+++ b/arch/ppc64/kernel/smp.c	2004-08-26 23:30:32 -07:00
@@ -59,6 +59,7 @@
 
 cpumask_t cpu_possible_map = CPU_MASK_NONE;
 cpumask_t cpu_online_map = CPU_MASK_NONE;
+cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
 
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_possible_map);
@@ -591,10 +592,7 @@
 
 void smp_local_timer_interrupt(struct pt_regs * regs)
 {
-	if (!--(get_paca()->prof_counter)) {
-		update_process_times(user_mode(regs));
-		(get_paca()->prof_counter)=get_paca()->prof_multiplier;
-	}
+	update_process_times(user_mode(regs));
 }
 
 void smp_message_recv(int msg, struct pt_regs *regs)
@@ -800,21 +798,12 @@
 
 static void __init smp_create_idle(unsigned int cpu)
 {
-	struct pt_regs regs;
 	struct task_struct *p;
 
 	/* create a process for the processor */
-	/* only regs.msr is actually used, and 0 is OK for it */
-	memset(&regs, 0, sizeof(struct pt_regs));
-	p = copy_process(CLONE_VM | CLONE_IDLETASK,
-			 0, &regs, 0, NULL, NULL);
+	p = fork_idle(cpu);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-
-	wake_up_forked_process(p);
-	init_idle(p, cpu);
-	unhash_process(p);
-
 	paca[cpu].__current = p;
 	current_set[cpu] = p->thread_info;
 }
@@ -832,8 +821,6 @@
 	/* Fixup boot cpu */
 	smp_store_cpu_info(boot_cpuid);
 	cpu_callin_map[boot_cpuid] = 1;
-	paca[boot_cpuid].prof_counter = 1;
-	paca[boot_cpuid].prof_multiplier = 1;
 
 #ifndef CONFIG_PPC_ISERIES
 	paca[boot_cpuid].next_jiffy_update_tb = tb_last_stamp = get_tb();
@@ -859,6 +846,12 @@
 	for_each_cpu(cpu)
 		if (cpu != boot_cpuid)
 			smp_create_idle(cpu);
+
+	for_each_cpu(cpu) {
+		cpu_set(cpu, cpu_sibling_map[cpu]);
+		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+			cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
+	}
 }
 
 void __devinit smp_prepare_boot_cpu(void)
@@ -880,8 +873,6 @@
 	if (system_state == SYSTEM_BOOTING && !cpu_present(cpu))
 		return -ENOENT;
 
-	paca[cpu].prof_counter = 1;
-	paca[cpu].prof_multiplier = 1;
 	paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock;
 
 	if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) {
@@ -1007,218 +998,3 @@
 
 	set_cpus_allowed(current, old_mask);
 }
-
-#ifdef CONFIG_SCHED_SMT
-#ifdef CONFIG_NUMA
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-		struct sched_domain *node_domain = &per_cpu(node_domains, i);
-		int node = cpu_to_node(i);
-		cpumask_t nodemask = node_to_cpumask(node);
-		cpumask_t my_cpumask = cpumask_of_cpu(i);
-		cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-			cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask);
-		else
-			cpu_domain->span = my_cpumask;
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = nodemask;
-		phys_domain->parent = node_domain;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-
-		*node_domain = SD_NODE_INIT;
-		node_domain->span = cpu_possible_map;
-		node_domain->groups = &sched_group_nodes[node];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		int j;
-		cpumask_t nodemask;
-		struct sched_group *node = &sched_group_nodes[i];
-		cpumask_t node_cpumask = node_to_cpumask(i);
-		cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-		if (cpus_empty(nodemask))
-			continue;
-
-		first = last = NULL;
-		/* Set up physical groups */
-		for_each_cpu_mask(j, nodemask) {
-			struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j);
-			struct sched_group *cpu = &sched_group_phys[j];
-
-			if (j != first_cpu(cpu_domain->span))
-				continue;
-
-			cpu->cpumask = cpu_domain->span;
-			/*
-			 * Make each extra sibling increase power by 10% of
-			 * the basic CPU. This is very arbitrary.
-			 */
-			cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-			node->cpu_power += cpu->cpu_power;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	/* Set up nodes */
-	first = last = NULL;
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		struct sched_group *cpu = &sched_group_nodes[i];
-		cpumask_t nodemask;
-		cpumask_t node_cpumask = node_to_cpumask(i);
-		cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-		if (cpus_empty(nodemask))
-			continue;
-
-		cpu->cpumask = nodemask;
-		/* ->cpu_power already setup */
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
-}
-#else /* !CONFIG_NUMA */
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-		cpumask_t my_cpumask = cpumask_of_cpu(i);
-		cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-			cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask);
-		else
-			cpu_domain->span = my_cpumask;
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = cpu_possible_map;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	first = last = NULL;
-	/* Set up physical groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_group *cpu = &sched_group_phys[i];
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		cpu->cpumask = cpu_domain->span;
-		/* See SMT+NUMA setup for comment */
-		cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
-}
-#endif /* CONFIG_NUMA */
-#endif /* CONFIG_SCHED_SMT */
diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c	2004-08-23 01:14:39 -07:00
+++ b/arch/ppc64/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -108,46 +108,6 @@
 
 static unsigned adjusting_time = 0;
 
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void ppc64_do_profile(struct pt_regs *regs)
-{
-	unsigned long nip;
-	extern unsigned long prof_cpu_mask;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	nip = instruction_pointer(regs);
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	nip -= (unsigned long)_stext;
-	nip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds EIP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (nip > prof_len-1)
-		nip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[nip]);
-}
-
 static __inline__ void timer_check_rtc(void)
 {
         /*
@@ -278,7 +238,7 @@
 	irq_enter();
 
 #ifndef CONFIG_PPC_ISERIES
-	ppc64_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #endif
 
 	lpaca->lppaca.xIntDword.xFields.xDecrInt = 0;
diff -Nru a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
--- a/arch/ppc64/kernel/vmlinux.lds.S	2004-04-12 10:53:59 -07:00
+++ b/arch/ppc64/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -61,12 +61,6 @@
 	__setup_end = .;
 	}
 
-  __param : {
-	__start___param = .;
-	*(__param)
-	__stop___param = .;
-	}
-
   .initcall.init : {
 	__initcall_start = .;
 	*(.initcall1.init)
diff -Nru a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile
--- a/arch/ppc64/mm/Makefile	2004-08-12 22:49:21 -07:00
+++ b/arch/ppc64/mm/Makefile	2004-08-24 02:08:17 -07:00
@@ -5,6 +5,6 @@
 EXTRA_CFLAGS += -mno-minimal-toc
 
 obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \
-	slb_low.o slb.o stab.o
+	slb_low.o slb.o stab.o mmap.o
 obj-$(CONFIG_DISCONTIGMEM) += numa.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff -Nru a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S
--- a/arch/ppc64/mm/hash_low.S	2004-04-12 10:54:08 -07:00
+++ b/arch/ppc64/mm/hash_low.S	2004-08-23 23:49:57 -07:00
@@ -278,6 +278,10 @@
 	b	bail
 
 htab_pte_insert_failure:
-	b	.htab_insert_failure
+	/* Bail out restoring old PTE */
+	ld	r6,STK_PARM(r6)(r1)
+	std	r31,0(r6)
+	li	r3,-1
+	b	bail
 
 
diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
--- a/arch/ppc64/mm/hash_utils.c	2004-07-28 20:37:40 -07:00
+++ b/arch/ppc64/mm/hash_utils.c	2004-08-23 23:49:57 -07:00
@@ -28,6 +28,7 @@
 #include <linux/ctype.h>
 #include <linux/cache.h>
 #include <linux/init.h>
+#include <linux/signal.h>
 
 #include <asm/ppcdebug.h>
 #include <asm/processor.h>
@@ -236,14 +237,11 @@
 	return pp;
 }
 
-/*
- * Called by asm hashtable.S in case of critical insert failure
+/* Result code is:
+ *  0 - handled
+ *  1 - normal page fault
+ * -1 - critical hash insertion error
  */
-void htab_insert_failure(void)
-{
-	panic("hash_page: pte_insert failed\n");
-}
-
 int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 {
 	void *pgdir;
@@ -369,6 +367,25 @@
 	*insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc));
 	flush_icache_range((unsigned long)insn_addr, 4+
 			   (unsigned long)insn_addr);
+}
+
+/*
+ * low_hash_fault is called when we the low level hash code failed
+ * to instert a PTE due to an hypervisor error
+ */
+void low_hash_fault(struct pt_regs *regs, unsigned long address)
+{
+	if (user_mode(regs)) {
+		siginfo_t info;
+
+		info.si_signo = SIGBUS;
+		info.si_errno = 0;
+		info.si_code = BUS_ADRERR;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGBUS, &info, current);
+		return;
+	}
+	bad_page_fault(regs, address, SIGBUS);
 }
 
 void __init htab_finish_init(void)
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	2004-08-23 01:14:43 -07:00
+++ b/arch/ppc64/mm/init.c	2004-08-24 02:08:33 -07:00
@@ -613,7 +613,7 @@
 	zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
 	zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
 
-	free_area_init_node(0, &contig_page_data, NULL, zones_size,
+	free_area_init_node(0, &contig_page_data, zones_size,
 			    __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
 	mem_map = contig_page_data.node_mem_map;
 }
diff -Nru a/arch/ppc64/mm/mmap.c b/arch/ppc64/mm/mmap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/mm/mmap.c	2004-08-24 02:08:17 -07:00
@@ -0,0 +1,86 @@
+/*
+ *  linux/arch/ppc64/mm/mmap.c
+ *
+ *  flexible mmap layout support
+ *
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * Started by Ingo Molnar <mingo@elte.hu>
+ */
+
+#include <linux/personality.h>
+#include <linux/mm.h>
+
+/*
+ * Top of mmap area (just below the process stack).
+ *
+ * Leave an at least ~128 MB hole.
+ */
+#define MIN_GAP (128*1024*1024)
+#define MAX_GAP (TASK_SIZE/6*5)
+
+static inline unsigned long mmap_base(void)
+{
+	unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur;
+
+	if (gap < MIN_GAP)
+		gap = MIN_GAP;
+	else if (gap > MAX_GAP)
+		gap = MAX_GAP;
+
+	return TASK_SIZE - (gap & PAGE_MASK);
+}
+
+static inline int mmap_is_legacy(void)
+{
+	/*
+	 * Force standard allocation for 64 bit programs.
+	 */
+	if (!test_thread_flag(TIF_32BIT))
+		return 1;
+
+	if (current->personality & ADDR_COMPAT_LAYOUT)
+		return 1;
+
+	if (current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
+		return 1;
+
+	return sysctl_legacy_va_layout;
+}
+
+/*
+ * This function, called very early during the creation of a new
+ * process VM image, sets up which VM layout function to use:
+ */
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	/*
+	 * Fall back to the standard layout if the personality
+	 * bit is set, or if the expected stack growth is unlimited:
+	 */
+	if (mmap_is_legacy()) {
+		mm->mmap_base = TASK_UNMAPPED_BASE;
+		mm->get_unmapped_area = arch_get_unmapped_area;
+		mm->unmap_area = arch_unmap_area;
+	} else {
+		mm->mmap_base = mmap_base();
+		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+		mm->unmap_area = arch_unmap_area_topdown;
+	}
+}
diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
--- a/arch/ppc64/mm/numa.c	2004-07-23 21:20:48 -07:00
+++ b/arch/ppc64/mm/numa.c	2004-08-24 11:06:27 -07:00
@@ -442,7 +442,6 @@
 {
 	unsigned long zones_size[MAX_NR_ZONES];
 	unsigned long zholes_size[MAX_NR_ZONES];
-	struct page *node_mem_map; 
 	int nid;
 
 	memset(zones_size, 0, sizeof(zones_size));
@@ -469,11 +468,11 @@
 		 * in free_area_init_node (which will fail).
 		 */
 		if (!node_data[nid].node_spanned_pages)
-			node_mem_map = alloc_bootmem(sizeof(struct page));
+			NODE_DATA(nid)->node_mem_map
+					= alloc_bootmem(sizeof(struct page));
 		else
-			node_mem_map = NULL;
-
-		free_area_init_node(nid, NODE_DATA(nid), node_mem_map,
-				    zones_size, start_pfn, zholes_size);
+			NODE_DATA(nid)->node_mem_map = NULL;
+		free_area_init_node(nid, NODE_DATA(nid), zones_size,
+							start_pfn, zholes_size);
 	}
 }
diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig
--- a/arch/s390/defconfig	2004-08-09 16:41:37 -07:00
+++ b/arch/s390/defconfig	2004-08-24 02:09:01 -07:00
@@ -419,7 +419,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -511,11 +510,12 @@
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES_GENERIC is not set
+# CONFIG_CRYPTO_AES is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
 # CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
diff -Nru a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c
--- a/arch/s390/kernel/compat_exec.c	2004-05-22 14:56:29 -07:00
+++ b/arch/s390/kernel/compat_exec.c	2004-08-27 00:02:34 -07:00
@@ -69,7 +69,7 @@
 		mpnt->vm_page_prot = PAGE_COPY;
 		mpnt->vm_flags = VM_STACK_FLAGS;
 		insert_vm_struct(mm, mpnt);
-		mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
 	} 
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
--- a/arch/s390/kernel/compat_linux.c	2004-05-10 04:25:37 -07:00
+++ b/arch/s390/kernel/compat_linux.c	2004-08-24 02:09:01 -07:00
@@ -725,8 +725,7 @@
 	int ret;
 	mm_segment_t old_fs = get_fs();
 	
-	if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
-	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
+	if (copy_siginfo_from_user32(&info, uinfo))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigqueueinfo(pid, sig, &info);
@@ -1219,7 +1218,7 @@
 	child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL);
         if (!newsp)
                 newsp = regs.gprs[15];
-        return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+        return do_fork(clone_flags, newsp, &regs, 0,
 		       parent_tidptr, child_tidptr);
 }
 
diff -Nru a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
--- a/arch/s390/kernel/compat_signal.c	2004-08-07 11:05:35 -07:00
+++ b/arch/s390/kernel/compat_signal.c	2004-08-25 10:13:41 -07:00
@@ -552,9 +552,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -604,9 +602,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -614,19 +610,14 @@
  */	
 
 void
-handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal32(unsigned long sig, struct k_sigaction *ka,
+		siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		setup_rt_frame32(sig, ka, info, oldset, regs);
 	else
 		setup_frame32(sig, ka, oldset, regs);
-
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
 
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
diff -Nru a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
--- a/arch/s390/kernel/process.c	2004-07-06 19:32:22 -07:00
+++ b/arch/s390/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -336,7 +336,7 @@
 	child_tidptr = (int __user *) regs.gprs[5];
         if (!newsp)
                 newsp = regs.gprs[15];
-        return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+        return do_fork(clone_flags, newsp, &regs, 0,
 		       parent_tidptr, child_tidptr);
 }
 
diff -Nru a/arch/s390/kernel/profile.c b/arch/s390/kernel/profile.c
--- a/arch/s390/kernel/profile.c	2004-06-12 20:52:28 -07:00
+++ b/arch/s390/kernel/profile.c	2004-08-26 23:30:30 -07:00
@@ -9,49 +9,11 @@
 
 static struct proc_dir_entry * root_irq_dir;
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-					int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file,
-					const char __user *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data;
-	unsigned long full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
-cpumask_t prof_cpu_mask = CPU_MASK_ALL;
-
 void init_irq_proc(void)
 {
-	struct proc_dir_entry *entry;
-
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", 0);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-		return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 }
diff -Nru a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
--- a/arch/s390/kernel/signal.c	2004-07-11 01:59:28 -07:00
+++ b/arch/s390/kernel/signal.c	2004-08-25 10:13:41 -07:00
@@ -358,9 +358,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -414,9 +412,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -424,20 +420,15 @@
  */	
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		setup_rt_frame(sig, ka, info, oldset, regs);
 	else
 		setup_frame(sig, ka, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -461,6 +452,7 @@
 	unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -494,7 +486,7 @@
 
 	/* Get signal to deliver.  When running under ptrace, at this point
 	   the debugger may change all our registers ... */
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
 	/* Depending on the signal settings we may need to revert the
 	   decision to restart the system call. */
@@ -513,14 +505,15 @@
 #ifdef CONFIG_S390_SUPPORT
 		if (test_thread_flag(TIF_31BIT)) {
 			extern void handle_signal32(unsigned long sig,
+						    struct k_sigaction *ka,
 						    siginfo_t *info,
 						    sigset_t *oldset,
 						    struct pt_regs *regs);
-			handle_signal32(signr, &info, oldset, regs);
+			handle_signal32(signr, &ka, &info, oldset, regs);
 			return 1;
 	        }
 #endif
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &ka, &info, oldset, regs);
 		return 1;
 	}
 
diff -Nru a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
--- a/arch/s390/kernel/smp.c	2004-07-11 01:59:30 -07:00
+++ b/arch/s390/kernel/smp.c	2004-08-24 02:08:12 -07:00
@@ -562,21 +562,15 @@
 
 static void __init smp_create_idle(unsigned int cpu)
 {
-	struct pt_regs regs;
 	struct task_struct *p;
 
 	/*
 	 *  don't care about the psw and regs settings since we'll never
 	 *  reschedule the forked task.
 	 */
-	memset(&regs, 0, sizeof(struct pt_regs));
-	p = copy_process(CLONE_VM | CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+	p = fork_idle(cpu);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-
-	wake_up_forked_process(p);
-	init_idle(p, cpu);
-	unhash_process(p);
 	current_set[cpu] = p;
 }
 
diff -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
--- a/arch/s390/kernel/time.c	2004-07-06 19:32:22 -07:00
+++ b/arch/s390/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -174,47 +174,7 @@
 
 
 #ifdef CONFIG_PROFILING
-extern char _stext, _etext;
-
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void s390_do_profile(struct pt_regs * regs)
-{
-	unsigned long eip;
-	extern cpumask_t prof_cpu_mask;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	eip = instruction_pointer(regs);
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!cpu_isset(smp_processor_id(), prof_cpu_mask))
-		return;
-
-	eip -= (unsigned long) &_stext;
-	eip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds EIP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (eip > prof_len-1)
-		eip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[eip]);
-}
+#define s390_do_profile(regs)	profile_tick(CPU_PROFILING, regs)
 #else
 #define s390_do_profile(regs)  do { ; } while(0)
 #endif /* CONFIG_PROFILING */
diff -Nru a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
--- a/arch/s390/kernel/vmlinux.lds.S	2004-04-12 10:53:59 -07:00
+++ b/arch/s390/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -78,9 +78,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff -Nru a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
--- a/arch/s390/kernel/vtime.c	2004-07-06 19:32:22 -07:00
+++ b/arch/s390/kernel/vtime.c	2004-08-24 02:09:01 -07:00
@@ -21,7 +21,7 @@
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
 
-#define VTIMER_MAGIC (0x4b87ad6e + 1)
+#define VTIMER_MAGIC (TIMER_MAGIC + 1)
 static ext_int_info_t ext_int_info_timer;
 DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
diff -Nru a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
--- a/arch/s390/mm/Makefile	2004-02-26 03:21:57 -08:00
+++ b/arch/s390/mm/Makefile	2004-08-24 02:08:16 -07:00
@@ -2,6 +2,6 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y	 := init.o fault.o ioremap.o extmem.o
+obj-y	 := init.o fault.o ioremap.o extmem.o mmap.o
 obj-$(CONFIG_CMM) += cmm.o
 
diff -Nru a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
--- a/arch/s390/mm/fault.c	2004-07-11 01:59:28 -07:00
+++ b/arch/s390/mm/fault.c	2004-08-27 06:24:18 -07:00
@@ -126,8 +126,8 @@
  * Send SIGSEGV to task.  This is an external routine
  * to keep the stack usage of do_page_fault small.
  */
-static void force_sigsegv(struct pt_regs *regs, unsigned long error_code,
-			  int si_code, unsigned long address)
+static void do_sigsegv(struct pt_regs *regs, unsigned long error_code,
+		       int si_code, unsigned long address)
 {
 	struct siginfo si;
 
@@ -282,7 +282,7 @@
         if (regs->psw.mask & PSW_MASK_PSTATE) {
                 tsk->thread.prot_addr = address;
                 tsk->thread.trap_no = error_code;
-		force_sigsegv(regs, error_code, si_code, address);
+		do_sigsegv(regs, error_code, si_code, address);
                 return;
 	}
 
diff -Nru a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/s390/mm/mmap.c	2004-08-24 02:08:16 -07:00
@@ -0,0 +1,83 @@
+/*
+ *  linux/arch/s390/mm/mmap.c
+ *
+ *  flexible mmap layout support
+ *
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * Started by Ingo Molnar <mingo@elte.hu>
+ */
+
+#include <linux/personality.h>
+#include <linux/mm.h>
+
+/*
+ * Top of mmap area (just below the process stack).
+ *
+ * Leave an at least ~128 MB hole.
+ */
+#define MIN_GAP (128*1024*1024)
+#define MAX_GAP (TASK_SIZE/6*5)
+
+static inline unsigned long mmap_base(void)
+{
+	unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur;
+
+	if (gap < MIN_GAP)
+		gap = MIN_GAP;
+	else if (gap > MAX_GAP)
+		gap = MAX_GAP;
+
+	return TASK_SIZE - (gap & PAGE_MASK);
+}
+
+static inline int mmap_is_legacy(void)
+{
+#ifdef CONFIG_ARCH_S390X
+	/*
+	 * Force standard allocation for 64 bit programs.
+	 */
+	if (!test_thread_flag(TIF_31BIT))
+		return 1;
+#endif
+	return sysctl_legacy_va_layout ||
+	    (current->personality & ADDR_COMPAT_LAYOUT) ||
+	    current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY;
+}
+
+/*
+ * This function, called very early during the creation of a new
+ * process VM image, sets up which VM layout function to use:
+ */
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	/*
+	 * Fall back to the standard layout if the personality
+	 * bit is set, or if the expected stack growth is unlimited:
+	 */
+	if (mmap_is_legacy()) {
+		mm->mmap_base = TASK_UNMAPPED_BASE;
+		mm->get_unmapped_area = arch_get_unmapped_area;
+		mm->unmap_area = arch_unmap_area;
+	} else {
+		mm->mmap_base = mmap_base();
+		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+		mm->unmap_area = arch_unmap_area_topdown;
+	}
+}
diff -Nru a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
--- a/arch/sh/kernel/process.c	2004-06-24 01:56:13 -07:00
+++ b/arch/sh/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -440,7 +440,7 @@
 {
 	if (!newsp)
 		newsp = regs.regs[15];
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+	return do_fork(clone_flags, newsp, &regs, 0,
 			(int __user *)parent_tidptr, (int __user *)child_tidptr);
 }
 
diff -Nru a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
--- a/arch/sh/kernel/signal.c	2004-02-13 07:19:27 -08:00
+++ b/arch/sh/kernel/signal.c	2004-08-25 17:37:26 -07:00
@@ -413,9 +413,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -490,9 +488,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
diff -Nru a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
--- a/arch/sh/kernel/smp.c	2004-05-10 04:25:47 -07:00
+++ b/arch/sh/kernel/smp.c	2004-08-24 02:08:12 -07:00
@@ -98,18 +98,11 @@
 int __cpu_up(unsigned int cpu)
 {
 	struct task_struct *tsk;
-	struct pt_regs regs;
 
-	memset(&regs, 0, sizeof(struct pt_regs));
-	tsk = copy_process(CLONE_VM | CLONE_IDLETASK, 0, &regs, 0, 0, 0);
+	tsk = fork_idle(cpu);
 
 	if (IS_ERR(tsk))
 		panic("Failed forking idle task for cpu %d\n", cpu);
-	
-	wake_up_forked_process(tsk);
-
-	init_idle(tsk, cpu);
-	unhash_process(tsk);
 	
 	tsk->thread_info->cpu = cpu;
 
diff -Nru a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
--- a/arch/sh/kernel/time.c	2004-06-24 01:56:12 -07:00
+++ b/arch/sh/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/smp.h>
+#include <linux/profile.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -250,36 +251,6 @@
 /* last time the RTC clock got updated */
 static long last_rtc_update;
 
-/* Profiling definitions */
-extern unsigned long prof_cpu_mask;
-extern unsigned int * prof_buffer;
-extern unsigned long prof_len;
-extern unsigned long prof_shift;
-extern char _stext;
-
-static inline void sh_do_profile(unsigned long pc)
-{
-	/* Don't profile cpu_idle.. */
-	if (!prof_buffer || !current->pid)
-		return;
-
-	if (pc >= 0xa0000000UL && pc < 0xc0000000UL)
-		pc -= 0x20000000;
-
-	pc -= (unsigned long)&_stext;
-	pc >>= prof_shift;
-
-	/*
-	 * Don't ignore out-of-bounds PC values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (pc > prof_len - 1)
-		pc = prof_len - 1;
-
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -287,9 +258,7 @@
 static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	do_timer(regs);
-
-	if (!user_mode(regs))
-		sh_do_profile(regs->pc);
+	profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
 	if (sh_mv.mv_heartbeat != NULL) 
diff -Nru a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
--- a/arch/sh/kernel/vmlinux.lds.S	2004-06-24 01:56:13 -07:00
+++ b/arch/sh/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -75,9 +75,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff -Nru a/arch/sh/mm/init.c b/arch/sh/mm/init.c
--- a/arch/sh/mm/init.c	2004-06-24 01:56:09 -07:00
+++ b/arch/sh/mm/init.c	2004-08-24 11:05:57 -07:00
@@ -214,8 +214,8 @@
 	 */
 	disable_mmu();
 #endif
-
-	free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
+	NODE_DATA(0)->node_mem_map = NULL;
+	free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 	/* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/
 	mem_map = NODE_DATA(0)->node_mem_map;
 
@@ -225,7 +225,7 @@
 	 */
 	zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT;
 	zones_size[ZONE_NORMAL] = 0;
-	free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
+	free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
 #endif
 }
 
diff -Nru a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
--- a/arch/sh64/kernel/process.c	2004-06-29 07:44:46 -07:00
+++ b/arch/sh64/kernel/process.c	2004-08-27 00:02:36 -07:00
@@ -820,7 +820,7 @@
 {
 	if (!newsp)
 		newsp = pregs->regs[15];
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, pregs, 0, 0, 0);
+	return do_fork(clone_flags, newsp, pregs, 0, 0, 0);
 }
 
 /*
@@ -901,7 +901,7 @@
 	 */
 	pc = thread_saved_pc(p);
 
-#if CONFIG_FRAME_POINTER
+#ifdef CONFIG_FRAME_POINTER
 	if (in_sh64_switch_to(pc)) {
 		sh64_switch_to_fp = (long) p->thread.sp;
 		/* r14 is saved at offset 4 in the sh64_switch_to frame */
diff -Nru a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
--- a/arch/sh64/kernel/signal.c	2004-06-29 07:44:46 -07:00
+++ b/arch/sh64/kernel/signal.c	2004-08-25 17:37:26 -07:00
@@ -520,9 +520,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -628,9 +626,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
diff -Nru a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
--- a/arch/sh64/kernel/time.c	2004-07-11 01:55:11 -07:00
+++ b/arch/sh64/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -298,37 +298,6 @@
 /* last time the RTC clock got updated */
 static long last_rtc_update = 0;
 
-static inline void sh64_do_profile(struct pt_regs *regs)
-{
-	extern int _stext;
-	unsigned long pc;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	/* Don't profile cpu_idle..  */
-	if (!prof_buffer || !current->pid)
-		return;
-
-	pc = instruction_pointer(regs);
-	pc -= (unsigned long) &_stext;
-	pc >>= prof_shift;
-
-	/*
-	 * Don't ignore out-of-bounds PC values silently, put them into the
-	 * last histogram slot, so if present, they will show up as a sharp
-	 * peak.
-	 */
-	if (pc > prof_len - 1)
-		pc = prof_len - 1;
-
-	/* We could just be sloppy and not lock against a re-entry on this
-	   increment, but the profiling code won't always be linked in anyway. */
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -340,8 +309,7 @@
 	ctc_last_interrupt = (unsigned long) current_ctc;
 
 	do_timer(regs);
-
-	sh64_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
 	{
diff -Nru a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S
--- a/arch/sh64/kernel/vmlinux.lds.S	2004-06-29 07:44:46 -07:00
+++ b/arch/sh64/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -106,9 +106,6 @@
   __setup_start = .;
   .init.setup : C_PHYS(.init.setup) { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : C_PHYS(__param) { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : C_PHYS(.initcall.init) {
   	*(.initcall1.init)
diff -Nru a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c
--- a/arch/sh64/mm/init.c	2004-07-11 01:55:11 -07:00
+++ b/arch/sh64/mm/init.c	2004-08-24 11:05:57 -07:00
@@ -122,8 +122,8 @@
 	 * All memory is good as ZONE_NORMAL (fall-through) and ZONE_DMA.
          */
 	zones_size[ZONE_DMA] = MAX_LOW_PFN - START_PFN;
-
-	free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
+	NODE_DATA(0)->node_mem_map = NULL;
+	free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 
 	/* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/
 	mem_map = NODE_DATA(0)->node_mem_map;
diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig
--- a/arch/sparc/Kconfig	2004-08-15 12:45:19 -07:00
+++ b/arch/sparc/Kconfig	2004-08-27 00:02:38 -07:00
@@ -23,7 +23,7 @@
 
 source "init/Kconfig"
 
-menu "General setup"
+menu "General machine setup"
 
 config VT
 	bool
diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
--- a/arch/sparc/kernel/process.c	2004-07-13 06:06:27 -07:00
+++ b/arch/sparc/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -435,8 +435,6 @@
 {
 	unsigned long parent_tid_ptr, child_tid_ptr;
 
-	clone_flags &= ~CLONE_IDLETASK;
-
 	parent_tid_ptr = regs->u_regs[UREG_I2];
 	child_tid_ptr = regs->u_regs[UREG_I4];
 
diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
--- a/arch/sparc/kernel/signal.c	2004-08-23 14:36:55 -07:00
+++ b/arch/sparc/kernel/signal.c	2004-08-25 22:52:03 -07:00
@@ -274,7 +274,7 @@
 	return;
 
 segv_and_exit:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_sigreturn(struct pt_regs *regs)
@@ -341,7 +341,7 @@
 	return;
 
 segv_and_exit:
-	send_sig(SIGSEGV, current, 1);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
@@ -401,7 +401,7 @@
 	spin_unlock_irq(&current->sighand->siglock);
 	return;
 segv:
-	send_sig(SIGSEGV, current, 1);
+	force_sig(SIGSEGV, current);
 }
 
 /* Checks if the fp is valid */
@@ -549,7 +549,7 @@
 sigill_and_return:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 
@@ -663,7 +663,7 @@
 sigill_and_return:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 static inline void
@@ -746,7 +746,7 @@
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 /* Setup a Solaris stack frame */
@@ -876,7 +876,7 @@
 sigill_and_return:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs)
@@ -889,7 +889,7 @@
 	synchronize_user_stack();
 
 	if (current_thread_info()->w_saved)
-		goto sigsegv_and_return;
+		return -EFAULT;
 
 	err = clear_user(uc, sizeof(*uc));
 	if (err)
@@ -930,9 +930,6 @@
 	 * we have already stuffed all of it with sync_user_stack
 	 */
 	return (err ? -EFAULT : 0);
-
-sigsegv_and_return:
-	do_exit(SIGSEGV);
 }
 
 /* Set the context for a svr4 application, this is Solaris way to sigreturn */
@@ -1018,7 +1015,7 @@
 	return (err ? -EFAULT : 0);
 
 sigsegv_and_return:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 static inline void
@@ -1036,8 +1033,6 @@
 		else
 			setup_frame(&ka->sa, regs, signr, oldset, info);
 	}
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
 	if (!(ka->sa.sa_flags & SA_NOMASK)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -1077,6 +1072,7 @@
 {
 	siginfo_t info;
 	struct sparc_deliver_cookie cookie;
+	struct k_sigaction ka;
 	int signr;
 
 	/*
@@ -1096,15 +1092,12 @@
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, &cookie);
+	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
 	if (signr > 0) {
-		struct k_sigaction *ka;
-		
-		ka = &current->sighand->action[signr-1];
-
 		if (cookie.restart_syscall)
-			syscall_restart(cookie.orig_i0, regs, &ka->sa);
-		handle_signal(signr, ka, &info, oldset, regs, svr4_signal);
+			syscall_restart(cookie.orig_i0, regs, &ka.sa);
+		handle_signal(signr, &ka, &info, oldset,
+			      regs, svr4_signal);
 		return 1;
 	}
 	if (cookie.restart_syscall &&
diff -Nru a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
--- a/arch/sparc/kernel/sun4d_smp.c	2004-08-07 11:03:28 -07:00
+++ b/arch/sparc/kernel/sun4d_smp.c	2004-08-26 23:30:31 -07:00
@@ -19,6 +19,7 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+#include <linux/profile.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -201,18 +202,9 @@
 			int no;
 
 			/* Cook up an idler for this guy. */
-			kernel_thread(start_secondary, NULL, CLONE_IDLETASK);
-
+			p = fork_idle(i);
 			cpucount++;
-
-			p = prev_task(&init_task);
-
-			init_idle(p, i);
-
 			current_set[i] = p->thread_info;
-
-			unhash_process(p);
-
 			for (no = 0; !cpu_find_by_instance(no, NULL, &mid)
 				     && mid != i; no++) ;
 
@@ -418,8 +410,6 @@
 	panic("Bogon SMP message pass.");
 }
 
-extern void sparc_do_profile(unsigned long pc, unsigned long o7);
-
 void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = hard_smp4d_processor_id();
@@ -437,8 +427,7 @@
 		show_leds(cpu);
 	}
 
-	if(!user_mode(regs))
-		sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+	profile_tick(CPU_PROFILING, regs);
 
 	if(!--prof_counter(cpu)) {
 		int user = user_mode(regs);
diff -Nru a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
--- a/arch/sparc/kernel/sun4m_smp.c	2004-08-07 11:03:28 -07:00
+++ b/arch/sparc/kernel/sun4m_smp.c	2004-08-26 23:30:31 -07:00
@@ -16,6 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+#include <linux/profile.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
@@ -173,18 +174,9 @@
 			int timeout;
 
 			/* Cook up an idler for this guy. */
-			kernel_thread(start_secondary, NULL, CLONE_IDLETASK);
-
+			p = fork_idle(i);
 			cpucount++;
-
-			p = prev_task(&init_task);
-
-			init_idle(p, i);
-
 			current_set[i] = p->thread_info;
-
-			unhash_process(p);
-
 			/* See trampoline.S for details... */
 			entry += ((i-1) * 3);
 
@@ -400,16 +392,13 @@
 	ccall_info.processors_out[i] = 1;
 }
 
-extern void sparc_do_profile(unsigned long pc, unsigned long o7);
-
 void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 
 	clear_profile_irq(cpu);
 
-	if(!user_mode(regs))
-		sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+	profile_tick(CPU_PROFILING, regs);
 
 	if(!--prof_counter(cpu)) {
 		int user = user_mode(regs);
diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c	2004-07-13 06:07:24 -07:00
+++ b/arch/sparc/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -79,38 +79,24 @@
 
 #endif
 
-static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-
-/* 32-bit Sparc specific profiling function. */
-void sparc_do_profile(unsigned long pc, unsigned long o7)
+unsigned long profile_pc(struct pt_regs *regs)
 {
-	if(prof_buffer && current->pid) {
-		extern int _stext;
-		extern int __copy_user_begin, __copy_user_end;
-		extern int __atomic_begin, __atomic_end;
-		extern int __bzero_begin, __bzero_end;
-		extern int __bitops_begin, __bitops_end;
-
-		if ((pc >= (unsigned long) &__copy_user_begin &&
-		     pc < (unsigned long) &__copy_user_end) ||
-		    (pc >= (unsigned long) &__atomic_begin &&
-		     pc < (unsigned long) &__atomic_end) ||
-		    (pc >= (unsigned long) &__bzero_begin &&
-		     pc < (unsigned long) &__bzero_end) ||
-		    (pc >= (unsigned long) &__bitops_begin &&
-		     pc < (unsigned long) &__bitops_end))
-			pc = o7;
-
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-
-		spin_lock(&ticker_lock);
-		if(pc < prof_len)
-			prof_buffer[pc]++;
-		else
-			prof_buffer[prof_len - 1]++;
-		spin_unlock(&ticker_lock);
-	}
+	extern int __copy_user_begin, __copy_user_end;
+	extern int __atomic_begin, __atomic_end;
+	extern int __bzero_begin, __bzero_end;
+	extern int __bitops_begin, __bitops_end;
+	unsigned long pc = regs->pc;
+
+	if ((pc >= (unsigned long) &__copy_user_begin &&
+	     pc < (unsigned long) &__copy_user_end) ||
+	    (pc >= (unsigned long) &__atomic_begin &&
+	     pc < (unsigned long) &__atomic_end) ||
+	    (pc >= (unsigned long) &__bzero_begin &&
+	     pc < (unsigned long) &__bzero_end) ||
+	    (pc >= (unsigned long) &__bitops_begin &&
+	     pc < (unsigned long) &__bitops_end))
+		pc = regs->u_regs[UREG_RETPC];
+	return pc;
 }
 
 __volatile__ unsigned int *master_l10_counter;
@@ -129,8 +115,7 @@
 	static long last_rtc_update;
 
 #ifndef CONFIG_SMP
-	if(!user_mode(regs))
-		sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+	profile_tick(CPU_PROFILING, regs);
 #endif
 
 	/* Protect counter clear so that do_gettimeoffset works */
diff -Nru a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
--- a/arch/sparc/kernel/vmlinux.lds.S	2004-04-12 10:53:59 -07:00
+++ b/arch/sparc/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -46,9 +46,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
--- a/arch/sparc/mm/srmmu.c	2004-08-07 11:03:28 -07:00
+++ b/arch/sparc/mm/srmmu.c	2004-08-24 02:08:33 -07:00
@@ -1341,7 +1341,7 @@
 		zones_size[ZONE_HIGHMEM] = npages;
 		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    pfn_base, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff -Nru a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
--- a/arch/sparc/mm/sun4c.c	2004-08-23 01:15:21 -07:00
+++ b/arch/sparc/mm/sun4c.c	2004-08-24 02:08:33 -07:00
@@ -2114,7 +2114,7 @@
 		zones_size[ZONE_HIGHMEM] = npages;
 		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    pfn_base, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	2004-08-23 14:41:15 -07:00
+++ b/arch/sparc64/defconfig	2004-08-27 18:48:17 -07:00
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Fri Aug 27 17:37:00 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -46,7 +48,7 @@
 CONFIG_STOP_MACHINE=y
 
 #
-# General setup
+# General machine setup
 #
 CONFIG_BBC_I2C=m
 CONFIG_VT=y
@@ -65,6 +67,7 @@
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=m
 CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
 # CONFIG_CPU_FREQ_24_API is not set
 CONFIG_SPARC64=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -118,6 +121,7 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_CIRRUS is not set
 CONFIG_FB_PM2=y
 # CONFIG_FB_PM2_FIFO_DISCONNECT is not set
@@ -153,7 +157,6 @@
 #
 # Console display driver support
 #
-# CONFIG_MDA_CONSOLE is not set
 # CONFIG_PROM_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -217,6 +220,7 @@
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
 # CONFIG_BLK_DEV_RAM is not set
 
 #
@@ -398,6 +402,7 @@
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
@@ -475,6 +480,7 @@
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
@@ -514,6 +520,7 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -580,6 +587,9 @@
 CONFIG_IP_NF_RAW=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 
 #
 # IPv6: Netfilter Configuration
@@ -1096,6 +1106,7 @@
 #
 CONFIG_I2C_ALGOBIT=y
 CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
 
 #
 # I2C Hardware Bus support
@@ -1120,6 +1131,7 @@
 CONFIG_I2C_VIA=m
 CONFIG_I2C_VIAPRO=m
 CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
 
 #
 # Hardware Sensors Chip support
@@ -1141,6 +1153,7 @@
 CONFIG_SENSORS_LM85=m
 CONFIG_SENSORS_LM90=m
 CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_SMSC47M1=m
 CONFIG_SENSORS_VIA686A=m
 CONFIG_SENSORS_W83781D=m
 CONFIG_SENSORS_W83L785TS=m
@@ -1263,6 +1276,7 @@
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 CONFIG_CIFS=m
@@ -1474,6 +1488,7 @@
 CONFIG_SND_AC97_CODEC=m
 CONFIG_SND_ALI5451=m
 CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
 CONFIG_SND_AU8810=m
 CONFIG_SND_AU8820=m
 CONFIG_SND_AU8830=m
@@ -1513,6 +1528,7 @@
 # ALSA USB devices
 #
 # CONFIG_SND_USB_AUDIO is not set
+CONFIG_SND_USB_USX2Y=m
 
 #
 # ALSA Sparc devices
@@ -1532,6 +1548,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
@@ -1597,7 +1614,6 @@
 # CONFIG_USB_IBMCAM is not set
 # CONFIG_USB_KONICAWC is not set
 # CONFIG_USB_OV511 is not set
-CONFIG_USB_PWC=m
 # CONFIG_USB_SE401 is not set
 CONFIG_USB_SN9C102=m
 # CONFIG_USB_STV680 is not set
@@ -1734,14 +1750,14 @@
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_STACK_DEBUG is not set
 # CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_HAVE_DEC_LOCK=y
@@ -1762,6 +1778,7 @@
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WHIRLPOOL=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
diff -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
--- a/arch/sparc64/kernel/process.c	2004-07-21 13:12:26 -07:00
+++ b/arch/sparc64/kernel/process.c	2004-08-24 02:08:42 -07:00
@@ -588,8 +588,6 @@
 {
 	int __user *parent_tid_ptr, *child_tid_ptr;
 
-	clone_flags &= ~CLONE_IDLETASK;
-
 #ifdef CONFIG_COMPAT
 	if (test_thread_flag(TIF_32BIT)) {
 		parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]);
diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
--- a/arch/sparc64/kernel/signal.c	2004-08-23 14:36:55 -07:00
+++ b/arch/sparc64/kernel/signal.c	2004-08-25 22:52:03 -07:00
@@ -84,8 +84,8 @@
 	regs->tnpc = npc;
 	err |= __get_user(regs->y, &((*grp)[MC_Y]));
 	err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
-	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
+	regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
+	regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
 	err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
 	err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
 	err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
@@ -135,7 +135,7 @@
 
 	return;
 do_sigsegv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void sparc64_get_context(struct pt_regs *regs)
@@ -226,7 +226,7 @@
 
 	return;
 do_sigsegv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 struct rt_signal_frame {
@@ -408,9 +408,9 @@
 	err |= __get_user(tstate, &sf->regs.tstate);
 	err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs));
 
-	/* User can only change condition codes in %tstate. */
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
-	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
+	/* User can only change condition codes and %asi in %tstate. */
+	regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
+	regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
 
 	err |= __get_user(fpu_save, &sf->fpu_save);
 	if (fpu_save)
@@ -439,7 +439,7 @@
 	spin_unlock_irq(&current->sighand->siglock);
 	return;
 segv:
-	send_sig(SIGSEGV, current, 1);
+	force_sig(SIGSEGV, current);
 }
 
 /* Checks if the fp is valid */
@@ -565,7 +565,7 @@
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
@@ -574,8 +574,6 @@
 {
 	setup_rt_frame(ka, regs, signr, oldset,
 		       (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
 	if (!(ka->sa.sa_flags & SA_NOMASK)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -615,6 +613,7 @@
 {
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
+	struct k_sigaction ka;
 	int signr;
 	
 	cookie.restart_syscall = restart_syscall;
@@ -632,15 +631,11 @@
 	}
 #endif	
 
-	signr = get_signal_to_deliver(&info, regs, &cookie);
+	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
 	if (signr > 0) {
-		struct k_sigaction *ka;
-
-		ka = &current->sighand->action[signr-1];
-
 		if (cookie.restart_syscall)
-			syscall_restart(orig_i0, regs, &ka->sa);
-		handle_signal(signr, ka, &info, oldset, regs);
+			syscall_restart(orig_i0, regs, &ka.sa);
+		handle_signal(signr, &ka, &info, oldset, regs);
 		return 1;
 	}
 	if (cookie.restart_syscall &&
diff -Nru a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
--- a/arch/sparc64/kernel/signal32.c	2004-08-23 14:36:55 -07:00
+++ b/arch/sparc64/kernel/signal32.c	2004-08-25 22:52:03 -07:00
@@ -59,6 +59,16 @@
 	unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
 };
 
+/* This magic should be in g_upper[0] for all upper parts
+ * to be valid.
+ */
+#define SIGINFO_EXTRA_V8PLUS_MAGIC	0x130e269
+typedef struct {
+	unsigned int g_upper[8];
+	unsigned int o_upper[8];
+	unsigned int asi;
+} siginfo_extra_v8plus_t;
+
 /* 
  * And the new one, intended to be used for Linux applications only
  * (we have enough in there to work with clone).
@@ -299,8 +309,13 @@
 	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
 		err |= __get_user(i, &sf->v8plus.g_upper[0]);
 		if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
+			unsigned long asi;
+
 			for (i = UREG_G1; i <= UREG_I7; i++)
 				err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+			err |= __get_user(asi, &sf->v8plus.asi);
+			regs->tstate &= ~TSTATE_ASI;
+			regs->tstate |= ((asi & 0xffUL) << 24UL);
 		}
 	}
 
@@ -330,7 +345,7 @@
 	return;
 
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_sigreturn32(struct pt_regs *regs)
@@ -400,7 +415,7 @@
 	return;
 
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
@@ -447,8 +462,13 @@
 	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
 		err |= __get_user(i, &sf->v8plus.g_upper[0]);
 		if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
+			unsigned long asi;
+
 			for (i = UREG_G1; i <= UREG_I7; i++)
 				err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+			err |= __get_user(asi, &sf->v8plus.asi);
+			regs->tstate &= ~TSTATE_ASI;
+			regs->tstate |= ((asi & 0xffUL) << 24UL);
 		}
 	}
 
@@ -487,7 +507,7 @@
 	spin_unlock_irq(&current->sighand->siglock);
 	return;
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 /* Checks if the fp is valid */
@@ -648,7 +668,7 @@
 	return;
 
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 
@@ -715,7 +735,10 @@
 	err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
 	err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
 	for (i = 1; i < 16; i++)
-		err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+		err |= __put_user(((u32 *)regs->u_regs)[2*i],
+				  &sf->v8plus.g_upper[i]);
+	err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
+			  &sf->v8plus.asi);
 
 	if (psr & PSR_EF) {
 		err |= save_fpu_state32(regs, &sf->fpu_state);
@@ -796,7 +819,7 @@
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 /* Setup a Solaris stack frame */
@@ -920,7 +943,7 @@
 	return;
 
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 asmlinkage int
@@ -1071,7 +1094,7 @@
 
 	return -EINTR;
 sigsegv:
-	do_exit(SIGSEGV);
+	return -EFAULT;
 }
 
 static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
@@ -1120,6 +1143,8 @@
 	for (i = 1; i < 16; i++)
 		err |= __put_user(((u32 *)regs->u_regs)[2*i],
 				  &sf->v8plus.g_upper[i]);
+	err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
+			  &sf->v8plus.asi);
 
 	if (psr & PSR_EF) {
 		err |= save_fpu_state32(regs, &sf->fpu_state);
@@ -1208,7 +1233,7 @@
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
@@ -1227,8 +1252,6 @@
 		else
 			setup_frame32(&ka->sa, regs, signr, oldset, info);
 	}
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
 	if (!(ka->sa.sa_flags & SA_NOMASK)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -1268,21 +1291,19 @@
 {
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
+	struct k_sigaction ka;
 	int signr;
 	int svr4_signal = current->personality == PER_SVR4;
 	
 	cookie.restart_syscall = restart_syscall;
 	cookie.orig_i0 = orig_i0;
 
-	signr = get_signal_to_deliver(&info, regs, &cookie);
+	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
 	if (signr > 0) {
-		struct k_sigaction *ka;
-
-		ka = &current->sighand->action[signr-1];
-
 		if (cookie.restart_syscall)
-			syscall_restart32(orig_i0, regs, &ka->sa);
-		handle_signal32(signr, ka, &info, oldset, regs, svr4_signal);
+			syscall_restart32(orig_i0, regs, &ka.sa);
+		handle_signal32(signr, &ka, &info, oldset,
+				regs, svr4_signal);
 		return 1;
 	}
 	if (cookie.restart_syscall &&
diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
--- a/arch/sparc64/kernel/smp.c	2004-08-06 23:01:03 -07:00
+++ b/arch/sparc64/kernel/smp.c	2004-08-26 23:30:31 -07:00
@@ -19,6 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/cache.h>
 #include <linux/jiffies.h>
+#include <linux/profile.h>
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
@@ -303,14 +304,7 @@
 	struct task_struct *p;
 	int timeout, ret, cpu_node;
 
-	kernel_thread(NULL, NULL, CLONE_IDLETASK);
-
-	p = prev_task(&init_task);
-
-	init_idle(p, cpu);
-
-	unhash_process(p);
-
+	p = fork_idle(cpu);
 	callin_flag = 0;
 	cpu_new_thread = p->thread_info;
 	cpu_set(cpu, cpu_callout_map);
@@ -981,8 +975,6 @@
 	smp_cross_call(&xcall_promstop, 0, 0, 0);
 }
 
-extern void sparc64_do_profile(struct pt_regs *regs);
-
 #define prof_multiplier(__cpu)		cpu_data(__cpu).multiplier
 #define prof_counter(__cpu)		cpu_data(__cpu).counter
 
@@ -1008,7 +1000,7 @@
 	}
 
 	do {
-		sparc64_do_profile(regs);
+		profile_tick(CPU_PROFILING, regs);
 		if (!--prof_counter(cpu)) {
 			irq_enter();
 
diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
--- a/arch/sparc64/kernel/sparc64_ksyms.c	2004-08-23 14:36:04 -07:00
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	2004-08-27 16:10:13 -07:00
@@ -372,6 +372,12 @@
 EXPORT_SYMBOL_NOVERS(memmove);
 EXPORT_SYMBOL_NOVERS(strncmp);
 
+/* Delay routines. */
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__ndelay);
+EXPORT_SYMBOL(__const_udelay);
+EXPORT_SYMBOL(__delay);
+
 void VISenter(void);
 /* RAID code needs this */
 EXPORT_SYMBOL_NOVERS(VISenter);
diff -Nru a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
--- a/arch/sparc64/kernel/sys32.S	2004-06-03 14:51:21 -07:00
+++ b/arch/sparc64/kernel/sys32.S	2004-08-26 17:50:55 -07:00
@@ -120,7 +120,7 @@
 SIGN2(sys32_setpgid, sys_setpgid, %o0, %o1)
 SIGN3(sys32_setpriority, sys_setpriority, %o0, %o1, %o2)
 SIGN1(sys32_ssetmask, sys_ssetmask, %o0)
-SIGN2(sys32_syslog, sys_syslog, %o0, %o1)
+SIGN2(sys32_syslog, sys_syslog, %o0, %o2)
 SIGN1(sys32_umask, sys_umask, %o0)
 SIGN3(sys32_tgkill, sys_tgkill, %o0, %o1, %o2)
 SIGN1(sys32_sendto, sys_sendto, %o0)
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c	2004-08-08 19:52:51 -07:00
+++ b/arch/sparc64/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -29,6 +29,7 @@
 #include <linux/jiffies.h>
 #include <linux/cpufreq.h>
 #include <linux/percpu.h>
+#include <linux/profile.h>
 
 #include <asm/oplib.h>
 #include <asm/mostek.h>
@@ -441,28 +442,6 @@
 	}
 }
 
-void sparc64_do_profile(struct pt_regs *regs)
-{
-	unsigned long pc;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	pc = regs->tpc;
-
-	pc -= (unsigned long) _stext;
-	pc >>= prof_shift;
-
-	if(pc >= prof_len)
-		pc = prof_len - 1;
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	unsigned long ticks, pstate;
@@ -471,7 +450,7 @@
 
 	do {
 #ifndef CONFIG_SMP
-		sparc64_do_profile(regs);
+		profile_tick(CPU_PROFILING, regs);
 #endif
 		do_timer(regs);
 
diff -Nru a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
--- a/arch/sparc64/kernel/vmlinux.lds.S	2004-04-12 10:53:59 -07:00
+++ b/arch/sparc64/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -52,9 +52,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff -Nru a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
--- a/arch/sparc64/lib/Makefile	2004-08-23 14:33:04 -07:00
+++ b/arch/sparc64/lib/Makefile	2004-08-27 16:10:13 -07:00
@@ -12,7 +12,7 @@
 	 U1memcpy.o U1copy_from_user.o U1copy_to_user.o \
 	 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
 	 copy_in_user.o user_fixup.o memmove.o \
-	 mcount.o ipcsum.o rwsem.o xor.o splock.o find_bit.o
+	 mcount.o ipcsum.o rwsem.o xor.o splock.o find_bit.o delay.o
 
 lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff -Nru a/arch/sparc64/lib/U1memcpy.S b/arch/sparc64/lib/U1memcpy.S
--- a/arch/sparc64/lib/U1memcpy.S	2004-08-23 14:34:42 -07:00
+++ b/arch/sparc64/lib/U1memcpy.S	2004-08-26 14:34:13 -07:00
@@ -117,6 +117,7 @@
 	.align		64
 
 	.globl		FUNC_NAME
+	.type		FUNC_NAME,#function
 FUNC_NAME:		/* %o0=dst, %o1=src, %o2=len */
 	PREAMBLE
 	mov		%o0, %g5
@@ -550,3 +551,5 @@
 	 add		%o1, 1, %o1
 	retl
 	 mov		EX_RETVAL(%g5), %o0
+
+	.size		FUNC_NAME, .-FUNC_NAME
diff -Nru a/arch/sparc64/lib/U3memcpy.S b/arch/sparc64/lib/U3memcpy.S
--- a/arch/sparc64/lib/U3memcpy.S	2004-08-23 14:33:04 -07:00
+++ b/arch/sparc64/lib/U3memcpy.S	2004-08-26 14:34:13 -07:00
@@ -78,6 +78,7 @@
 	 */
 
 	.globl	FUNC_NAME
+	.type	FUNC_NAME,#function
 FUNC_NAME:	/* %o0=dst, %o1=src, %o2=len */
 	PREAMBLE
 	mov		%o0, %g5
@@ -412,3 +413,5 @@
 	 add		%o1, 1, %o1
 	retl
 	 mov		EX_RETVAL(%g5), %o0
+
+	.size		FUNC_NAME, .-FUNC_NAME
diff -Nru a/arch/sparc64/lib/U3patch.S b/arch/sparc64/lib/U3patch.S
--- a/arch/sparc64/lib/U3patch.S	2004-08-23 14:32:55 -07:00
+++ b/arch/sparc64/lib/U3patch.S	2004-08-26 14:34:13 -07:00
@@ -22,9 +22,11 @@
 	flush	%g2;
 
 	.globl	cheetah_patch_copyops
+	.type	cheetah_patch_copyops,#function
 cheetah_patch_copyops:
 	ULTRA3_DO_PATCH(memcpy, U3memcpy)
 	ULTRA3_DO_PATCH(___copy_from_user, U3copy_from_user)
 	ULTRA3_DO_PATCH(___copy_to_user, U3copy_to_user)
 	retl
 	 nop
+	.size	cheetah_patch_copyops,.-cheetah_patch_copyops
diff -Nru a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
--- a/arch/sparc64/lib/atomic.S	2004-08-08 19:52:52 -07:00
+++ b/arch/sparc64/lib/atomic.S	2004-08-26 14:34:13 -07:00
@@ -10,6 +10,7 @@
 	.align	64
 
 	.globl	__atomic_add
+	.type	__atomic_add,#function
 __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
 	lduw	[%o1], %g5
 	add	%g5, %o0, %g7
@@ -19,8 +20,10 @@
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 add	%g7, %o0, %o0
+	.size	__atomic_add, .-__atomic_add
 
 	.globl	__atomic_sub
+	.type	__atomic_sub,#function
 __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
 	lduw	[%o1], %g5
 	sub	%g5, %o0, %g7
@@ -30,8 +33,10 @@
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 sub	%g7, %o0, %o0
+	.size	__atomic_sub, .-__atomic_sub
 
 	.globl	__atomic64_add
+	.type	__atomic64_add,#function
 __atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
 	ldx	[%o1], %g5
 	add	%g5, %o0, %g7
@@ -41,8 +46,10 @@
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 add	%g7, %o0, %o0
+	.size	__atomic64_add, .-__atomic64_add
 
 	.globl	__atomic64_sub
+	.type	__atomic64_sub,#function
 __atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */
 	ldx	[%o1], %g5
 	sub	%g5, %o0, %g7
@@ -52,4 +59,4 @@
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 sub	%g7, %o0, %o0
-
+	.size	__atomic64_sub, .-__atomic64_sub
diff -Nru a/arch/sparc64/lib/bitops.S b/arch/sparc64/lib/bitops.S
--- a/arch/sparc64/lib/bitops.S	2004-08-23 14:36:04 -07:00
+++ b/arch/sparc64/lib/bitops.S	2004-08-26 14:34:13 -07:00
@@ -9,6 +9,7 @@
 	.text
 	.align	64
 	.globl	___test_and_set_bit
+	.type	___test_and_set_bit,#function
 ___test_and_set_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
@@ -26,8 +27,10 @@
 	 ldx	[%o1], %g7
 2:	retl
 	 membar	#StoreLoad | #StoreStore
+	.size	___test_and_set_bit, .-___test_and_set_bit
 
 	.globl	___test_and_clear_bit
+	.type	___test_and_clear_bit,#function
 ___test_and_clear_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
@@ -45,8 +48,10 @@
 	 ldx	[%o1], %g7
 2:	retl
 	 membar	#StoreLoad | #StoreStore
+	.size	___test_and_clear_bit, .-___test_and_clear_bit
 
 	.globl	___test_and_change_bit
+	.type	___test_and_change_bit,#function
 ___test_and_change_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
@@ -64,3 +69,4 @@
 2:	retl
 	 membar	#StoreLoad | #StoreStore
 	nop
+	.size	___test_and_change_bit, .-___test_and_change_bit
diff -Nru a/arch/sparc64/lib/copy_in_user.S b/arch/sparc64/lib/copy_in_user.S
--- a/arch/sparc64/lib/copy_in_user.S	2004-08-23 14:32:55 -07:00
+++ b/arch/sparc64/lib/copy_in_user.S	2004-08-26 14:34:13 -07:00
@@ -31,7 +31,8 @@
 	 * to copy register windows around during thread cloning.
 	 */
 
-	.globl	___copy_in_user
+	.globl		___copy_in_user
+	.type		___copy_in_user,#function
 ___copy_in_user:	/* %o0=dst, %o1=src, %o2=len */
 	/* Writing to %asi is _expensive_ so we hardcode it.
 	 * Reading %asi to check for KERNEL_DS is comparatively
@@ -99,11 +100,14 @@
 	retl
 	 clr		%o0
 
+	.size		___copy_in_user, .-___copy_in_user
+
 	/* Act like copy_{to,in}_user(), ie. return zero instead
 	 * of original destination pointer.  This is invoked when
 	 * copy_{to,in}_user() finds that %asi is kernel space.
 	 */
 	.globl		memcpy_user_stub
+	.type		memcpy_user_stub,#function
 memcpy_user_stub:
 	save		%sp, -192, %sp
 	mov		%i0, %o0
@@ -112,3 +116,4 @@
 	 mov		%i2, %o2
 	ret
 	 restore	%g0, %g0, %o0
+	.size		memcpy_user_stub, .-memcpy_user_stub
diff -Nru a/arch/sparc64/lib/copy_page.S b/arch/sparc64/lib/copy_page.S
--- a/arch/sparc64/lib/copy_page.S	2004-08-11 15:15:08 -07:00
+++ b/arch/sparc64/lib/copy_page.S	2004-08-26 14:34:13 -07:00
@@ -45,6 +45,7 @@
 
 	.align		32
 	.globl		copy_user_page
+	.type		copy_user_page,#function
 copy_user_page:		/* %o0=dest, %o1=src, %o2=vaddr */
 	lduw		[%g6 + TI_PRE_COUNT], %o4
 	sethi		%uhi(PAGE_OFFSET), %g2
@@ -237,3 +238,5 @@
 
 	retl
 	 stw		%o4, [%g6 + TI_PRE_COUNT]
+
+	.size		copy_user_page, .-copy_user_page
diff -Nru a/arch/sparc64/lib/delay.c b/arch/sparc64/lib/delay.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/delay.c	2004-08-27 16:10:01 -07:00
@@ -0,0 +1,49 @@
+/* delay.c: Delay loops for sparc64
+ *
+ * Copyright (C) 2004 David S. Miller <davem@redhat.com>
+ *
+ * Based heavily upon x86 variant which is:
+ *	Copyright (C) 1993 Linus Torvalds
+ *	Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <linux/delay.h>
+
+void __delay(unsigned long loops)
+{
+	__asm__ __volatile__(
+"	b,pt	%%xcc, 1f\n"
+"	 cmp	%0, 0\n"
+"	.align	32\n"
+"1:\n"
+"	bne,pt	%%xcc, 1b\n"
+"	 subcc	%0, 1, %0\n"
+	: "=&r" (loops)
+	: "0" (loops)
+	: "cc");
+}
+
+/* We used to multiply by HZ after shifting down by 32 bits
+ * but that runs into problems for higher values of HZ and
+ * slow cpus.
+ */
+void __const_udelay(unsigned long n)
+{
+	n *= 4;
+
+	n *= (cpu_data(smp_processor_id()).udelay_val * (HZ/4));
+	n >>= 32;
+
+	__delay(n + 1);
+}
+
+void __udelay(unsigned long n)
+{
+	__const_udelay(n * 0x10c7UL);
+}
+
+
+void __ndelay(unsigned long n)
+{
+	__const_udelay(n * 0x5UL);
+}
diff -Nru a/arch/sparc64/lib/ipcsum.S b/arch/sparc64/lib/ipcsum.S
--- a/arch/sparc64/lib/ipcsum.S	2002-10-14 05:17:30 -07:00
+++ b/arch/sparc64/lib/ipcsum.S	2004-08-26 14:34:13 -07:00
@@ -1,6 +1,7 @@
 	.text
-	.align		32
-	.globl		ip_fast_csum
+	.align	32
+	.globl	ip_fast_csum
+	.type	ip_fast_csum,#function
 ip_fast_csum:	/* %o0 = iph, %o1 = ihl */
 	sub	%o1, 4, %g7
 	lduw	[%o0 + 0x00], %o2
@@ -30,3 +31,4 @@
 	set	0xffff, %o1
 	retl
 	 and	%o2, %o1, %o0
+	.size	ip_fast_csum, .-ip_fast_csum
diff -Nru a/arch/sparc64/lib/memmove.S b/arch/sparc64/lib/memmove.S
--- a/arch/sparc64/lib/memmove.S	2004-08-23 14:32:55 -07:00
+++ b/arch/sparc64/lib/memmove.S	2004-08-26 14:34:13 -07:00
@@ -5,8 +5,9 @@
  */
 
 	.text
-	.align	32
-	.globl	memmove
+	.align		32
+	.globl		memmove
+	.type		memmove,#function
 memmove:
 	mov		%o0, %g1
 	cmp		%o0, %o1
@@ -29,3 +30,4 @@
 
 	retl
 	 mov		%g1, %o0
+	.size		memmove, .-memmove
diff -Nru a/arch/sparc64/lib/splock.S b/arch/sparc64/lib/splock.S
--- a/arch/sparc64/lib/splock.S	2004-07-22 18:41:27 -07:00
+++ b/arch/sparc64/lib/splock.S	2004-08-26 14:34:13 -07:00
@@ -7,6 +7,7 @@
 	.align	64
 
 	.globl		_raw_spin_lock
+	.type		_raw_spin_lock,#function
 _raw_spin_lock:		/* %o0 = lock_ptr */
 1:	ldstub		[%o0], %g7
 	brnz,pn		%g7, 2f
@@ -17,8 +18,10 @@
 	brnz,pt		%g7, 2b
 	 membar		#LoadLoad
 	ba,a,pt		%xcc, 1b
+	.size		_raw_spin_lock, .-_raw_spin_lock
 
-	.globl	_raw_spin_lock_flags
+	.globl		_raw_spin_lock_flags
+	.type		_raw_spin_lock_flags,#function
 _raw_spin_lock_flags:	/* %o0 = lock_ptr, %o1 = irq_flags */
 1:	ldstub		[%o0], %g7
 	brnz,pn		%g7, 2f
@@ -33,3 +36,4 @@
 	 membar		#LoadLoad
 	ba,pt		%xcc, 1b		! Retry lock acquire
 	 wrpr		%g2, %pil		! Restore PIL
+	.size		_raw_spin_lock_flags, .-_raw_spin_lock_flags
diff -Nru a/arch/sparc64/lib/strlen.S b/arch/sparc64/lib/strlen.S
--- a/arch/sparc64/lib/strlen.S	2004-08-23 14:35:22 -07:00
+++ b/arch/sparc64/lib/strlen.S	2004-08-26 14:34:13 -07:00
@@ -9,7 +9,8 @@
 #define HI_MAGIC 0x80808080
 
 	.align	32
-	.global strlen
+	.globl	strlen
+	.type	strlen,#function
 strlen:
 	mov	%o0, %o1
 	andcc	%o0, 3, %g0
@@ -75,3 +76,5 @@
 13:
 	retl
 	 mov	2, %o0
+
+	.size	strlen, .-strlen
diff -Nru a/arch/sparc64/lib/strncmp.S b/arch/sparc64/lib/strncmp.S
--- a/arch/sparc64/lib/strncmp.S	2004-08-23 14:35:22 -07:00
+++ b/arch/sparc64/lib/strncmp.S	2004-08-26 14:34:13 -07:00
@@ -7,8 +7,9 @@
 #include <asm/asi.h>
 
 	.text
-	.align 4
-	.global strncmp
+	.align	32
+	.globl	strncmp
+	.type	strncmp,#function
 strncmp:
 	brlez,pn %o2, 3f
 	 lduba	[%o0] (ASI_PNF), %o3
@@ -28,3 +29,4 @@
 3:
 	retl
 	 clr	%o0
+	.size	strncmp, .-strncmp
diff -Nru a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S
--- a/arch/sparc64/lib/strncpy_from_user.S	2002-02-05 09:40:29 -08:00
+++ b/arch/sparc64/lib/strncpy_from_user.S	2004-08-26 14:34:13 -07:00
@@ -12,7 +12,7 @@
 0:	.xword	0x0101010101010101
 
 	.text
-	.align	4
+	.align	32
 
 	/* Must return:
 	 *
@@ -31,6 +31,7 @@
 	 */
 
 	.globl	__strncpy_from_user
+	.type	__strncpy_from_user,#function
 __strncpy_from_user:
 	/* %o0=dest, %o1=src, %o2=count */
 	sethi	%hi(0b), %o5		! IEU0	Group
@@ -122,6 +123,7 @@
 	 mov	%o2, %o0
 2:	retl
 	 add	%o2, %o3, %o0
+	.size	__strncpy_from_user, .-__strncpy_from_user
 
 	.section .fixup,#alloc,#execinstr
 	.align	4
diff -Nru a/arch/sparc64/lib/xor.S b/arch/sparc64/lib/xor.S
--- a/arch/sparc64/lib/xor.S	2003-07-07 23:57:36 -07:00
+++ b/arch/sparc64/lib/xor.S	2004-08-26 14:37:21 -07:00
@@ -18,8 +18,9 @@
  *	!(len & 127) && len >= 256
  */
 	.text
-	.globl xor_vis_2
-	.type xor_vis_2,@function
+	.align	32
+	.globl	xor_vis_2
+	.type	xor_vis_2,#function
 xor_vis_2:
 	rd	%fprs, %o5
 	andcc	%o5, FPRS_FEF|FPRS_DU, %g0
@@ -87,11 +88,10 @@
 	wr	%g1, %g0, %asi
 	retl
 	  wr	%g0, 0, %fprs
-	.size xor_vis_2, .-xor_vis_2
+	.size	xor_vis_2, .-xor_vis_2
 
-
-	.globl xor_vis_3
-	.type xor_vis_3,@function
+	.globl	xor_vis_3
+	.type	xor_vis_3,#function
 xor_vis_3:
 	rd	%fprs, %o5
 	andcc	%o5, FPRS_FEF|FPRS_DU, %g0
@@ -156,11 +156,10 @@
 	wr	%g1, %g0, %asi
 	retl
 	 wr	%g0, 0, %fprs
-	.size xor_vis_3, .-xor_vis_3
-
+	.size	xor_vis_3, .-xor_vis_3
 
-	.globl xor_vis_4
-	.type xor_vis_4,@function
+	.globl	xor_vis_4
+	.type	xor_vis_4,#function
 xor_vis_4:
 	rd	%fprs, %o5
 	andcc	%o5, FPRS_FEF|FPRS_DU, %g0
@@ -244,11 +243,10 @@
 	wr	%g1, %g0, %asi
 	retl
 	 wr	%g0, 0, %fprs
-	.size xor_vis_4, .-xor_vis_4
-
+	.size	xor_vis_4, .-xor_vis_4
 
-	.globl xor_vis_5
-	.type xor_vis_5,@function
+	.globl	xor_vis_5
+	.type	xor_vis_5,#function
 xor_vis_5:
 	mov	%o5, %g5
 	rd	%fprs, %o5
@@ -353,4 +351,4 @@
 	wr	%g1, %g0, %asi
 	retl
 	 wr	%g0, 0, %fprs
-	.size xor_vis_5, .-xor_vis_5
+	.size	xor_vis_5, .-xor_vis_5
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	2004-08-06 23:01:03 -07:00
+++ b/arch/sparc64/mm/init.c	2004-08-24 02:08:33 -07:00
@@ -1502,7 +1502,7 @@
 		zones_size[ZONE_DMA] = npages;
 		zholes_size[ZONE_DMA] = npages - pages_avail;
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    phys_base >> PAGE_SHIFT, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig
--- a/arch/um/Kconfig	2004-08-15 12:45:19 -07:00
+++ b/arch/um/Kconfig	2004-08-24 02:08:18 -07:00
@@ -61,6 +61,20 @@
 
 config NET
 	bool "Networking support"
+	help
+	Unless you really know what you are doing, you should say Y here.
+	The reason is that some programs need kernel networking support even
+	when running on a stand-alone machine that isn't connected to any
+	other computer. If you are upgrading from an older kernel, you
+	should consider updating your networking tools too because changes
+	in the kernel and the tools often go hand in hand. The tools are
+	contained in the package net-tools, the location and version number
+	of which are given in Documentation/Changes.
+
+	For a general introduction to Linux networking, it is highly
+	recommended to read the NET-HOWTO, available from
+	<http://www.tldp.org/docs.html#howto>.
+
 
 source "fs/Kconfig.binfmt"
 
@@ -85,6 +99,19 @@
         If you'd like to be able to work with files stored on the host,
         say Y or M here; otherwise say N.
 
+config HPPFS
+	tristate "HoneyPot ProcFS"
+	help
+	hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
+	entries to be overridden, removed, or fabricated from the host.
+	Its purpose is to allow a UML to appear to be a physical machine
+	by removing or changing anything in /proc which gives away the
+	identity of a UML.
+
+	See http://user-mode-linux.sf.net/hppfs.html for more information.
+
+	You only need this if you are setting up a UML honeypot.  Otherwise,
+	it is safe to say 'N' here.
 
 config MCONSOLE
 	bool "Management console"
@@ -163,6 +190,17 @@
 	This option determines the size of UML kernel stacks.  They will
 	be 1 << order pages.  The default is OK unless you're running Valgrind
 	on UML, in which case, set this to 3.
+
+config UML_REAL_TIME_CLOCK
+	bool "Real-time Clock"
+	default y
+	help
+	This option makes UML time deltas match wall clock deltas.  This should
+	normally be enabled.  The exception would be if you are debugging with
+	UML and spend long times with UML stopped at a breakpoint.  In this
+	case, when UML is restarted, it will call the timer enough times to make
+	up for the time spent at the breakpoint.  This could result in a
+	noticable lag.  If this is a problem, then disable this option.
 
 endmenu
 
diff -Nru a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
--- a/arch/um/Kconfig.debug	2004-08-15 12:45:39 -07:00
+++ b/arch/um/Kconfig.debug	2004-08-24 02:08:18 -07:00
@@ -9,6 +9,10 @@
 config PT_PROXY
 	bool "Enable ptrace proxy"
 	depends on XTERM_CHAN && DEBUG_INFO
+	help
+	This option enables a debugging interface which allows gdb to debug
+	the kernel without needing to actually attach to kernel threads.
+	If you want to do kernel debugging, say Y here; otherwise say N.
 
 config GPROF
 	bool "Enable gprof support"
diff -Nru a/arch/um/Kconfig_block b/arch/um/Kconfig_block
--- a/arch/um/Kconfig_block	2002-11-17 12:36:10 -08:00
+++ b/arch/um/Kconfig_block	2004-08-24 02:08:21 -07:00
@@ -29,6 +29,10 @@
         wise choice too.  In all other cases (for example, if you're just
         playing around with User-Mode Linux) you can choose N.
 
+config BLK_DEV_COW_COMMON
+	bool
+	default BLK_DEV_UBD
+
 config BLK_DEV_LOOP
 	tristate "Loopback device support"
 
diff -Nru a/arch/um/Kconfig_char b/arch/um/Kconfig_char
--- a/arch/um/Kconfig_char	2002-11-17 12:36:10 -08:00
+++ b/arch/um/Kconfig_char	2004-08-24 02:08:23 -07:00
@@ -108,11 +108,60 @@
 
 config UNIX98_PTYS
 	bool "Unix98 PTY support"
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
 
-config UNIX98_PTY_COUNT
-	int "Maximum number of Unix98 PTYs in use (0-2048)"
-	depends on UNIX98_PTYS
+	  Linux has traditionally used the BSD-like names /dev/ptyxx for
+	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
+	  has a number of problems. The GNU C library glibc 2.1 and later,
+	  however, supports the Unix98 naming standard: in order to acquire a
+	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
+	  terminal is then made available to the process and the pseudo
+	  terminal slave can be accessed as /dev/pts/<number>. What was
+	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
+
+	  All modern Linux systems use the Unix98 ptys.  Say Y unless
+	  you're on an embedded system and want to conserve memory.
+
+config LEGACY_PTYS
+	bool "Legacy (BSD) PTY support"
+	default y
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
+
+	  Linux has traditionally used the BSD-like names /dev/ptyxx
+	  for masters and /dev/ttyxx for slaves of pseudo
+	  terminals. This scheme has a number of problems, including
+	  security.  This option enables these legacy devices; on most
+	  systems, it is safe to say N.
+
+
+config LEGACY_PTY_COUNT
+	int "Maximum number of legacy PTY in use"
+	depends on LEGACY_PTYS
 	default "256"
+	---help---
+	  The maximum number of legacy PTYs that can be used at any one time.
+	  The default is 256, and should be more than enough.  Embedded
+	  systems may want to reduce this to save memory.
+
+	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
+	  architectures and 24 bytes on 64-bit architectures.
+
+#config UNIX98_PTY_COUNT
+#	int "Maximum number of Unix98 PTYs in use (0-2048)"
+#	depends on UNIX98_PTYS
+#	default "256"
 
 config WATCHDOG
 	bool "Watchdog Timer Support"
diff -Nru a/arch/um/Kconfig_net b/arch/um/Kconfig_net
--- a/arch/um/Kconfig_net	2002-11-17 10:26:53 -08:00
+++ b/arch/um/Kconfig_net	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 
-menu "Network Devices"
+menu "UML Network Devices"
 	depends on NET
 
 # UML virtual driver
@@ -175,74 +175,6 @@
         don't need UML networking, say N.
 	
         Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
-
-
-# Below are hardware-independent drivers mirrored from
-# drivers/net/Config.in. It would be nice if Linux
-# had HW independent drivers separated from the other
-# but it does not. Until then each non-ISA/PCI arch
-# needs to provide it's own menu of network drivers
-config DUMMY
-	tristate "Dummy net driver support"
-
-config BONDING
-	tristate "Bonding driver support"
-
-config EQUALIZER
-	tristate "EQL (serial line load balancing) support"
-
-config TUN
-	tristate "Universal TUN/TAP device driver support"
-
-config ETHERTAP
-	tristate "Ethertap network tap (OBSOLETE)"
-	depends on EXPERIMENTAL && NETLINK
-
-config PPP
-	tristate "PPP (point-to-point protocol) support"
-
-config PPP_MULTILINK
-	bool "PPP multilink support (EXPERIMENTAL)"
-	depends on PPP && EXPERIMENTAL
-
-config PPP_FILTER
-	bool "PPP filtering"
-	depends on PPP && FILTER
-
-config PPP_ASYNC
-	tristate "PPP support for async serial ports"
-	depends on PPP
-
-config PPP_SYNC_TTY
-	tristate "PPP support for sync tty ports"
-	depends on PPP
-
-config PPP_DEFLATE
-	tristate "PPP Deflate compression"
-	depends on PPP
-
-config PPP_BSDCOMP
-	tristate "PPP BSD-Compress compression"
-	depends on PPP
-
-config PPPOE
-	tristate "PPP over Ethernet (EXPERIMENTAL)"
-	depends on PPP && EXPERIMENTAL
-
-config SLIP
-	tristate "SLIP (serial line) support"
-
-config SLIP_COMPRESSED
-	bool "CSLIP compressed headers"
-	depends on SLIP=y
-
-config SLIP_SMART
-	bool "Keepalive and linefill"
-	depends on SLIP=y
-
-config SLIP_MODE_SLIP6
-	bool "Six bit SLIP encapsulation"
-	depends on SLIP=y
 
 endmenu
 
diff -Nru a/arch/um/Makefile b/arch/um/Makefile
--- a/arch/um/Makefile	2004-08-15 11:20:44 -07:00
+++ b/arch/um/Makefile	2004-08-24 02:08:30 -07:00
@@ -22,17 +22,21 @@
 			   $(ARCH_DIR)/sys-$(SUBARCH)/
 
 # Have to precede the include because the included Makefiles reference them.
-SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
-	include/asm-um/sigcontext.h include/asm-um/processor.h \
-	include/asm-um/ptrace.h include/asm-um/arch-signal.h
+SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \
+	arch-signal.h module.h
+SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
 
 ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
 	$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
 
 GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
 
-include $(ARCH_DIR)/Makefile-$(SUBARCH)
-include $(ARCH_DIR)/Makefile-os-$(OS)
+# This target adds dependencies to "prepare". They are defined in the included
+# Makefiles (see Makefile-i386).
+
+.PHONY: sys_prepare
+sys_prepare:
+	@:
 
 MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
 MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
@@ -41,6 +45,9 @@
   include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
 endif
 
+include $(ARCH_DIR)/Makefile-$(SUBARCH)
+include $(ARCH_DIR)/Makefile-os-$(OS)
+
 EXTRAVERSION := $(EXTRAVERSION)-1um
 
 ARCH_INCLUDE = -I$(ARCH_DIR)/include
@@ -52,14 +59,22 @@
 
 CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
 	-D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
-	$(MODE_INCLUDE)
+	-Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE)
+
+CFLAGS += $(call check_gcc,-fno-unit-at-a-time,)
 
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
+# These are needed for clean and mrproper, since in that case .config is not
+# included; the values here are meaningless
+
+CONFIG_NEST_LEVEL ?= 0
+CONFIG_KERNEL_HALF_GIGS ?=  0
+
 SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
 
 ifeq ($(CONFIG_MODE_SKAS), y)
-$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+$(SYS_HEADERS) : $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
 endif
 
 include/linux/version.h: arch/$(ARCH)/Makefile
@@ -71,8 +86,6 @@
 
 LDFLAGS_vmlinux = -r
 
-vmlinux: $(ARCH_DIR)/main.o 
-
 # These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT +
 # CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case.
 
@@ -98,55 +111,58 @@
 CONFIG_KERNEL_STACK_ORDER ?= 2
 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
 
-CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \
+CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \
 	-DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
 	-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
-	-DKERNEL_STACK_SIZE=$(STACK_SIZE)
-
-CPPFLAGS_$(LD_SCRIPT-y) = $(CPPFLAGS_vmlinux.lds) -P -C -Uum
+	-DKERNEL_STACK_SIZE=$(STACK_SIZE))
 
-LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
+export CPPFLAGS_$(LD_SCRIPT-y) = $(CPPFLAGS_vmlinux.lds) -P -C -Uum
 
-$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
-	$(call if_changed_dep,as_s_S)
+LD_SCRIPT-y := $(ARCH_DIR)/kernel/$(LD_SCRIPT-y)
 
 linux: vmlinux $(LD_SCRIPT-y)
 	$(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \
-		-o linux $(ARCH_DIR)/main.o vmlinux -L/usr/lib -lutil
+		-o linux vmlinux -L/usr/lib -lutil
 
 USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
 USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
+USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS))
 USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
 	$(MODE_INCLUDE)
 
 # To get a definition of F_SETSIG
 USER_CFLAGS += -D_GNU_SOURCE
 
+# From main Makefile, these options are set after including the ARCH makefile.
+# So copy them here.
+
+ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+USER_CFLAGS		+= -Os
+else
+USER_CFLAGS		+= -O2
+endif
+
+ifndef CONFIG_FRAME_POINTER
+USER_CFLAGS		+= -fomit-frame-pointer
+endif
+
+ifdef CONFIG_DEBUG_INFO
+USER_CFLAGS		+= -g
+endif
+
 CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds \
-	$(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS)
+	$(ARCH_DIR)/dyn_link.ld.s $(ARCH_DIR)/include/uml-config.h \
+	$(GEN_HEADERS)
 
-$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
-	$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
+	$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
 
 archmrproper:
-	for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
-	do \
-		$(MAKE) -C $$d archmrproper; \
-	done
-	rm -f $(CLEAN_FILES) $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \
-		$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
-
-archclean: sysclean
-	for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
-	do \
-		$(MAKE) -C $$d clean; \
-	done
-	find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-		-o -name '*.gcov' \) -type f -print | xargs rm -f
-	rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
+	@:
 
-archdep: 
-	for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done
+archclean:
+	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
+		-o -name '*.gcov' \) -type f -print | xargs rm -f
 
 $(SYMLINK_HEADERS):
 	cd $(TOPDIR)/$(dir $@) ; \
@@ -161,19 +177,32 @@
 $(ARCH_DIR)/os:
 	cd $(ARCH_DIR) && ln -sf os-$(OS) os
 
-$(ARCH_DIR)/include/uml-config.h :
-	sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
+# Generated files
+define filechk_umlconfig
+	sed 's/ CONFIG/ UML_CONFIG/'
+endef
+
+$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h
+	$(call filechk,umlconfig)
+
+filechk_gen_header = $<
 
 $(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
-	$< > $@
+	$(call filechk,gen_header)
 
 $(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
-	$< > $@
+	$(call filechk,gen_header)
 
-$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
-	$(ARCH_DIR)/util FORCE ;
+$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util \
+	sys_prepare FORCE ;
 
 $(ARCH_DIR)/util: FORCE
-	@$(call descend,$@,)
+	$(Q)$(MAKE) $(build)=$@
 
 export SUBARCH USER_CFLAGS OS
+
+all: linux
+
+define archhelp
+  echo  '* linux	- Binary kernel image (./linux)'
+endef
diff -Nru a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
--- a/arch/um/Makefile-i386	2002-11-20 20:04:10 -08:00
+++ b/arch/um/Makefile-i386	2004-08-24 02:08:18 -07:00
@@ -16,22 +16,27 @@
 
 SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
 
+sys_prepare: $(SYS_DIR)/sc.h
+
 prepare: $(SYS_HEADERS)
 
+filechk_$(SYS_DIR)/sc.h := $(SYS_UTIL_DIR)/mk_sc
+
 $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
-	$< > $@
+	$(call filechk,$@)
+
+filechk_$(SYS_DIR)/thread.h := $(SYS_UTIL_DIR)/mk_thread
 
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 
-	$< > $@
+	$(call filechk,$@)
 
-$(SYS_UTIL_DIR)/mk_sc: FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_sc: scripts/basic/fixdep include/config/MARKER FORCE ;
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) sys_prepare FORCE ;
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
 $(SYS_UTIL_DIR): include/asm FORCE
-	@$(call descend,$@,)
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR)
 
-sysclean :
-	rm -f $(SYS_HEADERS)
+CLEAN_FILES += $(SYS_HEADERS)
diff -Nru a/arch/um/Makefile-skas b/arch/um/Makefile-skas
--- a/arch/um/Makefile-skas	2004-08-15 11:20:44 -07:00
+++ b/arch/um/Makefile-skas	2004-08-24 02:08:18 -07:00
@@ -14,7 +14,7 @@
 LINK_SKAS = -Wl,-rpath,/lib 
 LD_SCRIPT_SKAS = dyn.lds
 
-GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+GEN_HEADERS += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
 
-$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
-	$(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
+$(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h :
+	$(Q)$(MAKE) $(build)=$(ARCH_DIR)/kernel/skas $@
diff -Nru a/arch/um/config.release b/arch/um/config.release
--- a/arch/um/config.release	2004-08-09 16:41:37 -07:00
+++ b/arch/um/config.release	2004-08-24 02:08:18 -07:00
@@ -227,7 +227,6 @@
 CONFIG_EXT2_FS=y
 CONFIG_SYSV_FS=m
 CONFIG_UDF_FS=m
-# CONFIG_UDF_RW is not set
 CONFIG_UFS_FS=m
 # CONFIG_UFS_FS_WRITE is not set
 
diff -Nru a/arch/um/defconfig b/arch/um/defconfig
--- a/arch/um/defconfig	2004-08-09 16:41:37 -07:00
+++ b/arch/um/defconfig	2004-08-24 02:08:30 -07:00
@@ -1,47 +1,77 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.8.1-mm3
+# Fri Aug 20 13:03:03 2004
 #
 CONFIG_USERMODE=y
 CONFIG_MMU=y
-CONFIG_SWAP=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CONFIG_LOG_BUF_SHIFT=14
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
 
 #
-# General Setup
+# UML-specific options
 #
 CONFIG_MODE_TT=y
 CONFIG_MODE_SKAS=y
 CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_HOSTFS=y
+CONFIG_HPPFS=y
 CONFIG_MCONSOLE=y
-CONFIG_MAGIC_SYSRQ=y
 # CONFIG_HOST_2G_2G is not set
 # CONFIG_UML_SMP is not set
 # CONFIG_SMP is not set
 CONFIG_NEST_LEVEL=0
 CONFIG_KERNEL_HALF_GIGS=1
 # CONFIG_HIGHMEM is not set
-CONFIG_PROC_MM=y
 CONFIG_KERNEL_STACK_ORDER=2
+CONFIG_UML_REAL_TIME_CLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CPUSETS is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 
 #
 # Loadable module support
 #
-CONFIG_MODULES=y
-# CONFIG_KMOD is not set
+# CONFIG_MODULES is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Character Devices
@@ -58,7 +88,8 @@
 CONFIG_CON_CHAN="xterm"
 CONFIG_SSL_CHAN="pty"
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_WATCHDOG is not set
 CONFIG_UML_SOUND=y
 CONFIG_SOUND=y
@@ -69,6 +100,7 @@
 #
 CONFIG_BLK_DEV_UBD=y
 # CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_COW_COMMON=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
@@ -78,7 +110,7 @@
 CONFIG_NETDEVICES=y
 
 #
-# Network Devices
+# UML Network Devices
 #
 CONFIG_UML_NET=y
 CONFIG_UML_NET_ETHERTAP=y
@@ -88,22 +120,6 @@
 CONFIG_UML_NET_MCAST=y
 # CONFIG_UML_NET_PCAP is not set
 CONFIG_UML_NET_SLIRP=y
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-CONFIG_SLIP=y
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
 
 #
 # Networking support
@@ -115,8 +131,6 @@
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 # CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -126,23 +140,24 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_INET_IPCOMP is not set
 # CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
 # CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -154,11 +169,24 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_KGDBOE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=y
 
 #
 # Ethernet (10 or 100Mbit)
@@ -170,83 +198,125 @@
 #
 
 #
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
 #
-# CONFIG_NET_RADIO is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Token Ring devices
 #
-# CONFIG_SHAPER is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=y
+# CONFIG_SLIP_COMPRESSED is not set
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # File systems
 #
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_REISER4_FS=y
+CONFIG_REISER4_LARGE_KEY=y
+# CONFIG_REISER4_CHECK is not set
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
 CONFIG_QUOTACTL=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
 # CONFIG_EFS_FS is not set
 CONFIG_JFFS_FS=y
 CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS_PROC_FS=y
+# CONFIG_JFFS_PROC_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=m
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_MINIX_FS=m
 # CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
 
 #
 # Network File Systems
 #
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
 # CONFIG_EXPORTFS is not set
-# CONFIG_CIFS is not set
 # CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -254,11 +324,11 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
 
 #
 # Native Language Support
 #
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
@@ -283,6 +353,7 @@
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -301,6 +372,7 @@
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -311,33 +383,14 @@
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 # CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
 
 #
 # SCSI support
 #
-CONFIG_SCSI=y
-CONFIG_GENERIC_ISA_DMA=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_DEBUG_QUEUES=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_DEBUG=y
+# CONFIG_SCSI is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -359,34 +412,46 @@
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
 #
 # CONFIG_MTD_CFI is not set
 # CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
 
 #
 # Self-contained MTD device drivers
 #
 # CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-CONFIG_MTD_BLKMTD=m
+CONFIG_MTD_BLKMTD=y
 
 #
 # Disk-On-Chip Device Drivers
 #
-# CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
 
 #
 # NAND Flash Device Drivers
@@ -396,6 +461,7 @@
 #
 # Kernel hacking
 #
+CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_INFO=y
diff -Nru a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
--- a/arch/um/drivers/Makefile	2003-02-03 14:19:36 -08:00
+++ b/arch/um/drivers/Makefile	2004-08-24 02:08:25 -07:00
@@ -1,5 +1,5 @@
 # 
-# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
 
@@ -15,7 +15,7 @@
 #pcap-objs := pcap_kern.o pcap_user.o $(PCAP)
 net-objs := net_kern.o net_user.o
 mconsole-objs := mconsole_kern.o mconsole_user.o
-hostaudio-objs := hostaudio_kern.o hostaudio_user.o
+hostaudio-objs := hostaudio_kern.o
 ubd-objs := ubd_kern.o ubd_user.o
 port-objs := port_kern.o port_user.o
 harddog-objs := harddog_kern.o harddog_user.o
@@ -39,6 +39,7 @@
 obj-$(CONFIG_TTY_CHAN) += tty.o 
 obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
+obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
 
 obj-y += stdio_console.o $(CHAN_OBJS)
 
@@ -46,18 +47,7 @@
 
 USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
 	null.o pty.o tty.o xterm.o
-USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
-
-modules:
-
-fastdep:
-
-dep:
-
-archmrproper: clean
-
diff -Nru a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
--- a/arch/um/drivers/chan_kern.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/chan_kern.c	2004-08-24 02:08:25 -07:00
@@ -8,6 +8,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
+#include <linux/string.h>
 #include <linux/tty_flip.h>
 #include <asm/irq.h>
 #include "chan_kern.h"
@@ -16,6 +17,7 @@
 #include "irq_user.h"
 #include "sigio.h"
 #include "line.h"
+#include "os.h"
 
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
@@ -86,6 +88,52 @@
 	.winch		= 0,
 };
 
+void generic_close(int fd, void *unused)
+{
+	os_close_file(fd);
+}
+
+int generic_read(int fd, char *c_out, void *unused)
+{
+	int n;
+
+	n = os_read_file(fd, c_out, sizeof(*c_out));
+
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-EIO);
+	return(n);
+}
+
+int generic_write(int fd, const char *buf, int n, void *unused)
+{
+	return(os_write_file(fd, buf, n));
+}
+
+int generic_window_size(int fd, void *unused, unsigned short *rows_out,
+			unsigned short *cols_out)
+{
+	int rows, cols;
+	int ret;
+
+	ret = os_window_size(fd, &rows, &cols);
+	if(ret < 0)
+		return(ret);
+
+	ret = ((*rows_out != rows) || (*cols_out != cols));
+
+	*rows_out = rows;
+	*cols_out = cols;
+
+	return(ret);
+}
+
+void generic_free(void *data)
+{
+	kfree(data);
+}
+
 static void tty_receive_char(struct tty_struct *tty, char ch)
 {
 	if(tty == NULL) return;
@@ -265,6 +313,11 @@
 {
 	int n = 0;
 
+	if(chan == NULL){
+		CONFIG_CHUNK(str, size, n, "none", 1);
+		return(n);
+	}
+
 	CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
 
 	if(chan->dev == NULL){
@@ -420,7 +473,8 @@
 		INIT_LIST_HEAD(chans);
 	}
 
-	if((out = strchr(str, ',')) != NULL){
+	out = strchr(str, ',');
+	if(out != NULL){
 		in = str;
 		*out = '\0';
 		out++;
@@ -475,12 +529,15 @@
 				goto out;
 			}
 			err = chan->ops->read(chan->fd, &c, chan->data);
-			if(err > 0) tty_receive_char(tty, c);
+			if(err > 0)
+				tty_receive_char(tty, c);
 		} while(err > 0);
+
 		if(err == 0) reactivate_fd(chan->fd, irq);
 		if(err == -EIO){
 			if(chan->primary){
-				if(tty != NULL) tty_hangup(tty);
+				if(tty != NULL)
+					tty_hangup(tty);
 				line_disable(dev, irq);
 				close_chan(chans);
 				free_chan(chans);
diff -Nru a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
--- a/arch/um/drivers/chan_user.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/chan_user.c	2004-08-24 02:08:25 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <termios.h>
-#include <fcntl.h>
 #include <string.h>
 #include <signal.h>
 #include <sys/stat.h>
@@ -22,33 +21,6 @@
 #include "choose-mode.h"
 #include "mode.h"
 
-void generic_close(int fd, void *unused)
-{
-	close(fd);
-}
-
-int generic_read(int fd, char *c_out, void *unused)
-{
-	int n;
-
-	n = read(fd, c_out, sizeof(*c_out));
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-EIO);
-	return(1);
-}
-
-int generic_write(int fd, const char *buf, int n, void *unused)
-{
-	int count;
-
-	count = write(fd, buf, n);
-	if(count < 0) return(-errno);
-	return(count);
-}
-
 int generic_console_write(int fd, const char *buf, int n, void *unused)
 {
 	struct termios save, new;
@@ -65,26 +37,6 @@
 	return(err);
 }
 
-int generic_window_size(int fd, void *unused, unsigned short *rows_out,
-			unsigned short *cols_out)
-{
-	struct winsize size;
-	int ret = 0;
-
-	if(ioctl(fd, TIOCGWINSZ, &size) == 0){
-		ret = ((*rows_out != size.ws_row) || 
-		       (*cols_out != size.ws_col));
-		*rows_out = size.ws_row;
-		*cols_out = size.ws_col;
-	}
-	return(ret);
-}
-
-void generic_free(void *data)
-{
-	kfree(data);
-}
-
 static void winch_handler(int sig)
 {
 }
@@ -100,14 +52,16 @@
 	struct winch_data *data = arg;
 	sigset_t sigs;
 	int pty_fd, pipe_fd;
+	int count, err;
 	char c = 1;
 
-	close(data->close_me);
+	os_close_file(data->close_me);
 	pty_fd = data->pty_fd;
 	pipe_fd = data->pipe_fd;
-	if(write(pipe_fd, &c, sizeof(c)) != sizeof(c))
+	count = os_write_file(pipe_fd, &c, sizeof(c));
+	if(count != sizeof(c))
 		printk("winch_thread : failed to write synchronization "
-		       "byte, errno = %d\n", errno);
+		       "byte, err = %d\n", -count);
 
 	signal(SIGWINCH, winch_handler);
 	sigfillset(&sigs);
@@ -123,26 +77,24 @@
 		exit(1);
 	}
 
-	if(ioctl(pty_fd, TIOCSCTTY, 0) < 0){
-		printk("winch_thread : TIOCSCTTY failed, errno = %d\n", errno);
-		exit(1);
-	}
-	if(tcsetpgrp(pty_fd, os_getpid()) < 0){
-		printk("winch_thread : tcsetpgrp failed, errno = %d\n", errno);
+	err = os_new_tty_pgrp(pty_fd, os_getpid());
+	if(err < 0){
+		printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
 		exit(1);
 	}
 
-	if(read(pipe_fd, &c, sizeof(c)) != sizeof(c))
+	count = os_read_file(pipe_fd, &c, sizeof(c));
+	if(count != sizeof(c))
 		printk("winch_thread : failed to read synchronization byte, "
-		       "errno = %d\n", errno);
+		       "err = %d\n", -count);
 
 	while(1){
 		pause();
 
-		if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)){
-			printk("winch_thread : write failed, errno = %d\n",
-			       errno);
-		}
+		count = os_write_file(pipe_fd, &c, sizeof(c));
+		if(count != sizeof(c))
+			printk("winch_thread : write failed, err = %d\n",
+			       -count);
 	}
 }
 
@@ -154,8 +106,8 @@
 	char c;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("winch_tramp : os_pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("winch_tramp : os_pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -168,12 +120,12 @@
 		return(pid);
 	}
 
-	close(fds[1]);
+	os_close_file(fds[1]);
 	*fd_out = fds[0];
-	n = read(fds[0], &c, sizeof(c));
+	n = os_read_file(fds[0], &c, sizeof(c));
 	if(n != sizeof(c)){
 		printk("winch_tramp : failed to read synchronization byte\n");
-		printk("read returned %d, errno = %d\n", n, errno);
+		printk("read failed, err = %d\n", -n);
 		printk("fd %d will not support SIGWINCH\n", fd);
 		*fd_out = -1;
 	}
@@ -183,20 +135,24 @@
 void register_winch(int fd, void *device_data)
 {
 	int pid, thread, thread_fd;
+	int count;
 	char c = 1;
 
-	if(!isatty(fd)) return;
+	if(!isatty(fd))
+		return;
 
 	pid = tcgetpgrp(fd);
-	if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) && 
-	   (pid == -1)){
+	if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
+			     device_data) && (pid == -1)){
 		thread = winch_tramp(fd, device_data, &thread_fd);
 		if(fd != -1){
 			register_winch_irq(thread_fd, fd, thread, device_data);
 
-			if(write(thread_fd, &c, sizeof(c)) != sizeof(c))
+			count = os_write_file(thread_fd, &c, sizeof(c));
+			if(count != sizeof(c))
 				printk("register_winch : failed to write "
-				       "synchronization byte\n");
+				       "synchronization byte, err = %d\n",
+					-count);
 		}
 	}
 }
diff -Nru a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/drivers/cow.h	2004-08-24 11:13:13 -07:00
@@ -0,0 +1,41 @@
+#ifndef __COW_H__
+#define __COW_H__
+
+#include <asm/types.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define ntohll(x) (x)
+# define htonll(x) (x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+# define ntohll(x)  bswap_64(x)
+# define htonll(x)  bswap_64(x)
+#else
+#error "__BYTE_ORDER not defined"
+#endif
+
+extern int init_cow_file(int fd, char *cow_file, char *backing_file,
+			 int sectorsize, int alignment, int *bitmap_offset_out,
+			 unsigned long *bitmap_len_out, int *data_offset_out);
+
+extern int file_reader(__u64 offset, char *buf, int len, void *arg);
+extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
+			   void *arg, __u32 *version_out,
+			   char **backing_file_out, time_t *mtime_out,
+			   __u64 *size_out, int *sectorsize_out,
+			   __u32 *align_out, int *bitmap_offset_out);
+
+extern int write_cow_header(char *cow_file, int fd, char *backing_file,
+			    int sectorsize, int alignment, long long *size);
+
+extern void cow_sizes(int version, __u64 size, int sectorsize, int align,
+		      int bitmap_offset, unsigned long *bitmap_len_out,
+		      int *data_offset_out);
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/drivers/cow_sys.h	2004-08-24 11:13:14 -07:00
@@ -0,0 +1,48 @@
+#ifndef __COW_SYS_H__
+#define __COW_SYS_H__
+
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+#include "user.h"
+
+static inline void *cow_malloc(int size)
+{
+	return(um_kmalloc(size));
+}
+
+static inline void cow_free(void *ptr)
+{
+	kfree(ptr);
+}
+
+#define cow_printf printk
+
+static inline char *cow_strdup(char *str)
+{
+	return(uml_strdup(str));
+}
+
+static inline int cow_seek_file(int fd, __u64 offset)
+{
+	return(os_seek_file(fd, offset));
+}
+
+static inline int cow_file_size(char *file, __u64 *size_out)
+{
+	return(os_file_size(file, size_out));
+}
+
+static inline int cow_write_file(int fd, char *buf, int size)
+{
+	return(os_write_file(fd, buf, size));
+}
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/drivers/cow_user.c	2004-08-24 11:13:14 -07:00
@@ -0,0 +1,375 @@
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <netinet/in.h>
+
+#include "os.h"
+
+#include "cow.h"
+#include "cow_sys.h"
+
+#define PATH_LEN_V1 256
+
+struct cow_header_v1 {
+	int magic;
+	int version;
+	char backing_file[PATH_LEN_V1];
+	time_t mtime;
+	__u64 size;
+	int sectorsize;
+};
+
+#define PATH_LEN_V2 MAXPATHLEN
+
+struct cow_header_v2 {
+	unsigned long magic;
+	unsigned long version;
+	char backing_file[PATH_LEN_V2];
+	time_t mtime;
+	__u64 size;
+	int sectorsize;
+};
+
+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
+ * case other systems have different values for MAXPATHLEN
+ */
+#define PATH_LEN_V3 4096
+
+/* Changes from V2 -
+ *	PATH_LEN_V3 as described above
+ *	Explicitly specify field bit lengths for systems with different
+ *		lengths for the usual C types.  Not sure whether char or
+ *		time_t should be changed, this can be changed later without
+ *		breaking compatibility
+ *	Add alignment field so that different alignments can be used for the
+ *		bitmap and data
+ * 	Add cow_format field to allow for the possibility of different ways
+ *		of specifying the COW blocks.  For now, the only value is 0,
+ * 		for the traditional COW bitmap.
+ *	Move the backing_file field to the end of the header.  This allows
+ *		for the possibility of expanding it into the padding required
+ *		by the bitmap alignment.
+ * 	The bitmap and data portions of the file will be aligned as specified
+ * 		by the alignment field.  This is to allow COW files to be
+ *		put on devices with restrictions on access alignments, such as
+ *		/dev/raw, with a 512 byte alignment restriction.  This also
+ *		allows the data to be more aligned more strictly than on
+ *		sector boundaries.  This is needed for ubd-mmap, which needs
+ *		the data to be page aligned.
+ *	Fixed (finally!) the rounding bug
+ */
+
+struct cow_header_v3 {
+	__u32 magic;
+	__u32 version;
+	time_t mtime;
+	__u64 size;
+	__u32 sectorsize;
+	__u32 alignment;
+	__u32 cow_format;
+	char backing_file[PATH_LEN_V3];
+};
+
+/* COW format definitions - for now, we have only the usual COW bitmap */
+#define COW_BITMAP 0
+
+union cow_header {
+	struct cow_header_v1 v1;
+	struct cow_header_v2 v2;
+	struct cow_header_v3 v3;
+};
+
+#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
+#define COW_VERSION 3
+
+#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len))
+#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align)
+
+void cow_sizes(int version, __u64 size, int sectorsize, int align,
+	       int bitmap_offset, unsigned long *bitmap_len_out,
+	       int *data_offset_out)
+{
+	if(version < 3){
+		*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
+
+		*data_offset_out = bitmap_offset + *bitmap_len_out;
+		*data_offset_out = (*data_offset_out + sectorsize - 1) /
+			sectorsize;
+		*data_offset_out *= sectorsize;
+	}
+	else {
+		*bitmap_len_out = DIV_ROUND(size, sectorsize);
+		*bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8);
+
+		*data_offset_out = bitmap_offset + *bitmap_len_out;
+		*data_offset_out = ROUND_UP(*data_offset_out, align);
+	}
+}
+
+static int absolutize(char *to, int size, char *from)
+{
+	char save_cwd[256], *slash;
+	int remaining;
+
+	if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
+		cow_printf("absolutize : unable to get cwd - errno = %d\n",
+			   errno);
+		return(-1);
+	}
+	slash = strrchr(from, '/');
+	if(slash != NULL){
+		*slash = '\0';
+		if(chdir(from)){
+			*slash = '/';
+			cow_printf("absolutize : Can't cd to '%s' - "
+				   "errno = %d\n", from, errno);
+			return(-1);
+		}
+		*slash = '/';
+		if(getcwd(to, size) == NULL){
+			cow_printf("absolutize : unable to get cwd of '%s' - "
+			       "errno = %d\n", from, errno);
+			return(-1);
+		}
+		remaining = size - strlen(to);
+		if(strlen(slash) + 1 > remaining){
+			cow_printf("absolutize : unable to fit '%s' into %d "
+			       "chars\n", from, size);
+			return(-1);
+		}
+		strcat(to, slash);
+	}
+	else {
+		if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
+			cow_printf("absolutize : unable to fit '%s' into %d "
+			       "chars\n", from, size);
+			return(-1);
+		}
+		strcpy(to, save_cwd);
+		strcat(to, "/");
+		strcat(to, from);
+	}
+	chdir(save_cwd);
+	return(0);
+}
+
+int write_cow_header(char *cow_file, int fd, char *backing_file,
+		     int sectorsize, int alignment, long long *size)
+{
+	struct cow_header_v3 *header;
+	unsigned long modtime;
+	int err;
+
+	err = cow_seek_file(fd, 0);
+	if(err < 0){
+		cow_printf("write_cow_header - lseek failed, err = %d\n", -err);
+		goto out;
+	}
+
+	err = -ENOMEM;
+	header = cow_malloc(sizeof(*header));
+	if(header == NULL){
+		cow_printf("Failed to allocate COW V3 header\n");
+		goto out;
+	}
+	header->magic = htonl(COW_MAGIC);
+	header->version = htonl(COW_VERSION);
+
+	err = -EINVAL;
+	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+		cow_printf("Backing file name \"%s\" is too long - names are "
+			   "limited to %d characters\n", backing_file,
+			   sizeof(header->backing_file) - 1);
+		goto out_free;
+	}
+
+	if(absolutize(header->backing_file, sizeof(header->backing_file),
+		      backing_file))
+		goto out_free;
+
+	err = os_file_modtime(header->backing_file, &modtime);
+	if(err < 0){
+		cow_printf("Backing file '%s' mtime request failed, "
+			   "err = %d\n", header->backing_file, -err);
+		goto out_free;
+	}
+
+	err = cow_file_size(header->backing_file, size);
+	if(err < 0){
+		cow_printf("Couldn't get size of backing file '%s', "
+			   "err = %d\n", header->backing_file, -err);
+		goto out_free;
+	}
+
+	header->mtime = htonl(modtime);
+	header->size = htonll(*size);
+	header->sectorsize = htonl(sectorsize);
+	header->alignment = htonl(alignment);
+	header->cow_format = COW_BITMAP;
+
+	err = os_write_file(fd, header, sizeof(*header));
+	if(err != sizeof(*header)){
+		cow_printf("Write of header to new COW file '%s' failed, "
+			   "err = %d\n", cow_file, -err);
+		goto out_free;
+	}
+	err = 0;
+ out_free:
+	cow_free(header);
+ out:
+	return(err);
+}
+
+int file_reader(__u64 offset, char *buf, int len, void *arg)
+{
+	int fd = *((int *) arg);
+
+	return(pread(fd, buf, len, offset));
+}
+
+/* XXX Need to sanity-check the values read from the header */
+
+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
+		    __u32 *version_out, char **backing_file_out,
+		    time_t *mtime_out, __u64 *size_out,
+		    int *sectorsize_out, __u32 *align_out,
+		    int *bitmap_offset_out)
+{
+	union cow_header *header;
+	char *file;
+	int err, n;
+	unsigned long version, magic;
+
+	header = cow_malloc(sizeof(*header));
+	if(header == NULL){
+	        cow_printf("read_cow_header - Failed to allocate header\n");
+		return(-ENOMEM);
+	}
+	err = -EINVAL;
+	n = (*reader)(0, (char *) header, sizeof(*header), arg);
+	if(n < offsetof(typeof(header->v1), backing_file)){
+		cow_printf("read_cow_header - short header\n");
+		goto out;
+	}
+
+	magic = header->v1.magic;
+	if(magic == COW_MAGIC) {
+		version = header->v1.version;
+	}
+	else if(magic == ntohl(COW_MAGIC)){
+		version = ntohl(header->v1.version);
+	}
+	/* No error printed because the non-COW case comes through here */
+	else goto out;
+
+	*version_out = version;
+
+	if(version == 1){
+		if(n < sizeof(header->v1)){
+			cow_printf("read_cow_header - failed to read V1 "
+				   "header\n");
+			goto out;
+		}
+		*mtime_out = header->v1.mtime;
+		*size_out = header->v1.size;
+		*sectorsize_out = header->v1.sectorsize;
+		*bitmap_offset_out = sizeof(header->v1);
+		*align_out = *sectorsize_out;
+		file = header->v1.backing_file;
+	}
+	else if(version == 2){
+		if(n < sizeof(header->v2)){
+			cow_printf("read_cow_header - failed to read V2 "
+				   "header\n");
+			goto out;
+		}
+		*mtime_out = ntohl(header->v2.mtime);
+		*size_out = ntohll(header->v2.size);
+		*sectorsize_out = ntohl(header->v2.sectorsize);
+		*bitmap_offset_out = sizeof(header->v2);
+		*align_out = *sectorsize_out;
+		file = header->v2.backing_file;
+	}
+	else if(version == 3){
+		if(n < sizeof(header->v3)){
+			cow_printf("read_cow_header - failed to read V2 "
+				   "header\n");
+			goto out;
+		}
+		*mtime_out = ntohl(header->v3.mtime);
+		*size_out = ntohll(header->v3.size);
+		*sectorsize_out = ntohl(header->v3.sectorsize);
+		*align_out = ntohl(header->v3.alignment);
+		*bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
+		file = header->v3.backing_file;
+	}
+	else {
+		cow_printf("read_cow_header - invalid COW version\n");
+		goto out;
+	}
+	err = -ENOMEM;
+	*backing_file_out = cow_strdup(file);
+	if(*backing_file_out == NULL){
+		cow_printf("read_cow_header - failed to allocate backing "
+			   "file\n");
+		goto out;
+	}
+	err = 0;
+ out:
+	cow_free(header);
+	return(err);
+}
+
+int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
+		  int alignment, int *bitmap_offset_out,
+		  unsigned long *bitmap_len_out, int *data_offset_out)
+{
+	__u64 size, offset;
+	char zero = 0;
+	int err;
+
+	err = write_cow_header(cow_file, fd, backing_file, sectorsize,
+			       alignment, &size);
+	if(err)
+		goto out;
+
+	*bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
+	cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out,
+		  bitmap_len_out, data_offset_out);
+
+	offset = *data_offset_out + size - sizeof(zero);
+	err = cow_seek_file(fd, offset);
+	if(err < 0){
+		cow_printf("cow bitmap lseek failed : err = %d\n", -err);
+		goto out;
+	}
+
+	/* does not really matter how much we write it is just to set EOF
+	 * this also sets the entire COW bitmap
+	 * to zero without having to allocate it
+	 */
+	err = cow_write_file(fd, &zero, sizeof(zero));
+	if(err != sizeof(zero)){
+		cow_printf("Write of bitmap to new COW file '%s' failed, "
+			   "err = %d\n", cow_file, -err);
+		err = -EINVAL;
+		goto out;
+	}
+
+	return(0);
+
+ out:
+	return(err);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
--- a/arch/um/drivers/daemon_user.c	2003-02-05 07:18:58 -08:00
+++ b/arch/um/drivers/daemon_user.c	2004-08-24 02:08:18 -07:00
@@ -53,7 +53,8 @@
 	struct request_v3 req;
 	int fd, n, err;
 
-	if((pri->control = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
+	pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
+	if(pri->control < 0){
 		printk("daemon_open : control socket failed, errno = %d\n", 
 		       errno);		
 		return(-errno);
@@ -67,7 +68,8 @@
 		goto out;
 	}
 
-	if((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){
+	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if(fd < 0){
 		printk("daemon_open : data socket failed, errno = %d\n", 
 		       errno);
 		err = -errno;
@@ -91,18 +93,18 @@
 	req.version = SWITCH_VERSION;
 	req.type = REQ_NEW_CONTROL;
 	req.sock = *local_addr;
-	n = write(pri->control, &req, sizeof(req));
+	n = os_write_file(pri->control, &req, sizeof(req));
 	if(n != sizeof(req)){
-		printk("daemon_open : control setup request returned %d, "
-		       "errno = %d\n", n, errno);
+		printk("daemon_open : control setup request failed, err = %d\n",
+		       -n);
 		err = -ENOTCONN;
 		goto out;		
 	}
 
-	n = read(pri->control, sun, sizeof(*sun));
+	n = os_read_file(pri->control, sun, sizeof(*sun));
 	if(n != sizeof(*sun)){
-		printk("daemon_open : read of data socket returned %d, "
-		       "errno = %d\n", n, errno);
+		printk("daemon_open : read of data socket failed, err = %d\n",
+		       -n);
 		err = -ENOTCONN;
 		goto out_close;		
 	}
@@ -111,9 +113,9 @@
 	return(fd);
 
  out_close:
-	close(fd);
+	os_close_file(fd);
  out:
-	close(pri->control);
+	os_close_file(pri->control);
 	return(err);
 }
 
@@ -153,8 +155,8 @@
 {
 	struct daemon_data *pri = data;
 
-	close(pri->fd);
-	close(pri->control);
+	os_close_file(pri->fd);
+	os_close_file(pri->control);
 	if(pri->data_addr != NULL) kfree(pri->data_addr);
 	if(pri->ctl_addr != NULL) kfree(pri->ctl_addr);
 	if(pri->local_addr != NULL) kfree(pri->local_addr);
diff -Nru a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
--- a/arch/um/drivers/fd.c	2003-02-05 20:16:01 -08:00
+++ b/arch/um/drivers/fd.c	2004-08-24 02:08:18 -07:00
@@ -35,7 +35,8 @@
 		printk("fd_init : couldn't parse file descriptor '%s'\n", str);
 		return(NULL);
 	}
-	if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct fd_chan) { .fd  	= n,
 				    .raw  	= opts->raw });
 	return(data);
diff -Nru a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
--- a/arch/um/drivers/harddog_user.c	2002-12-29 16:18:43 -08:00
+++ b/arch/um/drivers/harddog_user.c	2004-08-24 02:08:18 -07:00
@@ -27,10 +27,10 @@
 	dup2(data->stdin, 0);
 	dup2(data->stdout, 1);
 	dup2(data->stdout, 2);
-	close(data->stdin);
-	close(data->stdout);
-	close(data->close_me[0]);
-	close(data->close_me[1]);
+	os_close_file(data->stdin);
+	os_close_file(data->stdout);
+	os_close_file(data->close_me[0]);
+	os_close_file(data->close_me[1]);
 }
 
 int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
@@ -44,15 +44,15 @@
 	char **args = NULL;
 
 	err = os_pipe(in_fds, 1, 0);
-	if(err){
-		printk("harddog_open - os_pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("harddog_open - os_pipe failed, err = %d\n", -err);
+		goto out;
 	}
 
 	err = os_pipe(out_fds, 1, 0);
-	if(err){
-		printk("harddog_open - os_pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("harddog_open - os_pipe failed, err = %d\n", -err);
+		goto out_close_in;
 	}
 
 	data.stdin = out_fds[0];
@@ -72,42 +72,47 @@
 
 	pid = run_helper(pre_exec, &data, args, NULL);
 
-	close(out_fds[0]);
-	close(in_fds[1]);
+	os_close_file(out_fds[0]);
+	os_close_file(in_fds[1]);
 
 	if(pid < 0){
 		err = -pid;
-		printk("harddog_open - run_helper failed, errno = %d\n", err);
-		goto out;
+		printk("harddog_open - run_helper failed, errno = %d\n", -err);
+		goto out_close_out;
 	}
 
-	n = read(in_fds[0], &c, sizeof(c));
+	n = os_read_file(in_fds[0], &c, sizeof(c));
 	if(n == 0){
 		printk("harddog_open - EOF on watchdog pipe\n");
 		helper_wait(pid);
 		err = -EIO;
-		goto out;
+		goto out_close_out;
 	}
 	else if(n < 0){
 		printk("harddog_open - read of watchdog pipe failed, "
-		       "errno = %d\n", errno);
+		       "err = %d\n", -n);
 		helper_wait(pid);
-		err = -errno;
-		goto out;
+		err = n;
+		goto out_close_out;
 	}
 	*in_fd_ret = in_fds[0];
 	*out_fd_ret = out_fds[1];
 	return(0);
+
+ out_close_in:
+	os_close_file(in_fds[0]);
+	os_close_file(in_fds[1]);
+ out_close_out:
+	os_close_file(out_fds[0]);
+	os_close_file(out_fds[1]);
  out:
-	close(out_fds[1]);
-	close(in_fds[0]);
 	return(err);
 }
 
 void stop_watchdog(int in_fd, int out_fd)
 {
-	close(in_fd);
-	close(out_fd);
+	os_close_file(in_fd);
+	os_close_file(out_fd);
 }
 
 int ping_watchdog(int fd)
@@ -115,11 +120,12 @@
 	int n;
 	char c = '\n';
 
-	n = write(fd, &c, sizeof(c));
-	if(n < sizeof(c)){
-		printk("ping_watchdog - write failed, errno = %d\n",
-		       errno);
-		return(-errno);
+	n = os_write_file(fd, &c, sizeof(c));
+	if(n != sizeof(c)){
+		printk("ping_watchdog - write failed, err = %d\n", -n);
+		if(n < 0)
+			return(n);
+		return(-EIO);
 	}
 	return 1;
 
diff -Nru a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
--- a/arch/um/drivers/hostaudio_kern.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/hostaudio_kern.c	2004-08-24 02:08:25 -07:00
@@ -5,44 +5,64 @@
 
 #include "linux/config.h"
 #include "linux/module.h"
-#include "linux/version.h"
 #include "linux/init.h"
 #include "linux/slab.h"
 #include "linux/fs.h"
 #include "linux/sound.h"
 #include "linux/soundcard.h"
+#include "asm/uaccess.h"
 #include "kern_util.h"
 #include "init.h"
-#include "hostaudio.h"
+#include "os.h"
+
+struct hostaudio_state {
+  int fd;
+};
+
+struct hostmixer_state {
+  int fd;
+};
+
+#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
+#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
 
 /* Only changed from linux_main at boot time */
 char *dsp = HOSTAUDIO_DEV_DSP;
 char *mixer = HOSTAUDIO_DEV_MIXER;
 
+#define DSP_HELP \
+"    This is used to specify the host dsp device to the hostaudio driver.\n" \
+"    The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
+
+#define MIXER_HELP \
+"    This is used to specify the host mixer device to the hostaudio driver.\n" \
+"    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
+
 #ifndef MODULE
 static int set_dsp(char *name, int *add)
 {
-	dsp = uml_strdup(name);
+	dsp = name;
 	return(0);
 }
 
-__uml_setup("dsp=", set_dsp,
-"dsp=<dsp device>\n"
-"    This is used to specify the host dsp device to the hostaudio driver.\n"
-"    The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
-);
+__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
 
 static int set_mixer(char *name, int *add)
 {
-	mixer = uml_strdup(name);
+	mixer = name;
 	return(0);
 }
 
-__uml_setup("mixer=", set_mixer,
-"mixer=<mixer device>\n"
-"    This is used to specify the host mixer device to the hostaudio driver.\n"
-"    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
-);
+__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
+
+#else /*MODULE*/
+
+MODULE_PARM(dsp, "s");
+MODULE_PARM_DESC(dsp, DSP_HELP);
+
+MODULE_PARM(mixer, "s");
+MODULE_PARM_DESC(mixer, MIXER_HELP);
+
 #endif
 
 /* /dev/dsp file operations */
@@ -51,23 +71,55 @@
 			      loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int ret;
 
 #ifdef DEBUG
         printk("hostaudio: read called, count = %d\n", count);
 #endif
 
-        return(hostaudio_read_user(state, buffer, count, ppos));
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if(kbuf == NULL)
+		return(-ENOMEM);
+
+	ret = os_read_file(state->fd, kbuf, count);
+	if(ret < 0)
+		goto out;
+
+	if(copy_to_user(buffer, kbuf, ret))
+		ret = -EFAULT;
+
+ out:
+	kfree(kbuf);
+	return(ret);
 }
 
 static ssize_t hostaudio_write(struct file *file, const char *buffer, 
 			       size_t count, loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int ret;
 
 #ifdef DEBUG
         printk("hostaudio: write called, count = %d\n", count);
 #endif
-        return(hostaudio_write_user(state, buffer, count, ppos));
+
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if(kbuf == NULL)
+		return(-ENOMEM);
+
+	ret = -EFAULT;
+	if(copy_from_user(kbuf, buffer, count))
+		goto out;
+
+	ret = os_write_file(state->fd, kbuf, count);
+	if(ret < 0)
+		goto out;
+
+ out:
+	kfree(kbuf);
+	return(ret);
 }
 
 static unsigned int hostaudio_poll(struct file *file, 
@@ -86,12 +138,43 @@
 			   unsigned int cmd, unsigned long arg)
 {
         struct hostaudio_state *state = file->private_data;
+	unsigned long data = 0;
+	int ret;
 
 #ifdef DEBUG
         printk("hostaudio: ioctl called, cmd = %u\n", cmd);
 #endif
+	switch(cmd){
+	case SNDCTL_DSP_SPEED:
+	case SNDCTL_DSP_STEREO:
+	case SNDCTL_DSP_GETBLKSIZE:
+	case SNDCTL_DSP_CHANNELS:
+	case SNDCTL_DSP_SUBDIVIDE:
+	case SNDCTL_DSP_SETFRAGMENT:
+		if(get_user(data, (int *) arg))
+			return(-EFAULT);
+		break;
+	default:
+		break;
+	}
+
+	ret = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
+
+	switch(cmd){
+	case SNDCTL_DSP_SPEED:
+	case SNDCTL_DSP_STEREO:
+	case SNDCTL_DSP_GETBLKSIZE:
+	case SNDCTL_DSP_CHANNELS:
+	case SNDCTL_DSP_SUBDIVIDE:
+	case SNDCTL_DSP_SETFRAGMENT:
+		if(put_user(data, (int *) arg))
+			return(-EFAULT);
+		break;
+	default:
+		break;
+	}
 
-        return(hostaudio_ioctl_user(state, cmd, arg));
+	return(ret);
 }
 
 static int hostaudio_open(struct inode *inode, struct file *file)
@@ -110,12 +193,17 @@
         if(file->f_mode & FMODE_READ) r = 1;
         if(file->f_mode & FMODE_WRITE) w = 1;
 
-        ret = hostaudio_open_user(state, r, w, dsp);
+	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
+
         if(ret < 0){
+		printk("hostaudio_open failed to open '%s', err = %d\n",
+		       dsp, -ret);
 		kfree(state);
 		return(ret);
         }
 
+	state->fd = ret;
+
         file->private_data = state;
         return(0);
 }
@@ -123,16 +211,19 @@
 static int hostaudio_release(struct inode *inode, struct file *file)
 {
         struct hostaudio_state *state = file->private_data;
-        int ret;
 
 #ifdef DEBUG
         printk("hostaudio: release called\n");
 #endif
 
-        ret = hostaudio_release_user(state);
+	if(state->fd >= 0){
+		os_close_file(state->fd);
+		state->fd = -1;
+	}
+
         kfree(state);
 
-        return(ret);
+	return(0);
 }
 
 /* /dev/mixer file operations */
@@ -146,7 +237,7 @@
         printk("hostmixer: ioctl called\n");
 #endif
 
-        return(hostmixer_ioctl_mixdev_user(state, cmd, arg));
+	return(os_ioctl_generic(state->fd, cmd, arg));
 }
 
 static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
@@ -165,13 +256,17 @@
         if(file->f_mode & FMODE_READ) r = 1;
         if(file->f_mode & FMODE_WRITE) w = 1;
 
-        ret = hostmixer_open_mixdev_user(state, r, w, mixer);
+	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
         
         if(ret < 0){
+		printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
+		       dsp, -ret);
 		kfree(state);
 		return(ret);
         }
 
+	state->fd = ret;
+
         file->private_data = state;
         return(0);
 }
@@ -179,16 +274,18 @@
 static int hostmixer_release(struct inode *inode, struct file *file)
 {
         struct hostmixer_state *state = file->private_data;
-	int ret;
 
 #ifdef DEBUG
         printk("hostmixer: release called\n");
 #endif
 
-        ret = hostmixer_release_mixdev_user(state);
+	if(state->fd >= 0){
+		os_close_file(state->fd);
+		state->fd = -1;
+	}
         kfree(state);
 
-        return(ret);
+	return(0);
 }
 
 
@@ -225,7 +322,8 @@
 
 static int __init hostaudio_init_module(void)
 {
-        printk(KERN_INFO "UML Audio Relay\n");
+        printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
+	       dsp, mixer);
 
 	module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
         if(module_data.dev_audio < 0){
diff -Nru a/arch/um/drivers/hostaudio_user.c b/arch/um/drivers/hostaudio_user.c
--- a/arch/um/drivers/hostaudio_user.c	2002-09-06 10:29:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,149 +0,0 @@
-/* 
- * Copyright (C) 2002 Steve Schmidtke 
- * Licensed under the GPL
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include "hostaudio.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "os.h"
-
-/* /dev/dsp file operations */
-
-ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer, 
-			    size_t count, loff_t *ppos)
-{
-	ssize_t ret;
-
-#ifdef DEBUG
-        printk("hostaudio: read_user called, count = %d\n", count);
-#endif
-
-        ret = read(state->fd, buffer, count);
-
-        if(ret < 0) return(-errno);
-        return(ret);
-}
-
-ssize_t hostaudio_write_user(struct hostaudio_state *state, const char *buffer,
-			     size_t count, loff_t *ppos)
-{
-	ssize_t ret;
-
-#ifdef DEBUG
-        printk("hostaudio: write_user called, count = %d\n", count);
-#endif
-
-        ret = write(state->fd, buffer, count);
-
-        if(ret < 0) return(-errno);
-        return(ret);
-}
-
-int hostaudio_ioctl_user(struct hostaudio_state *state, unsigned int cmd, 
-			 unsigned long arg)
-{
-	int ret;
-#ifdef DEBUG
-        printk("hostaudio: ioctl_user called, cmd = %u\n", cmd);
-#endif
-
-        ret = ioctl(state->fd, cmd, arg);
-	
-        if(ret < 0) return(-errno);
-        return(ret);
-}
-
-int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp)
-{
-#ifdef DEBUG
-        printk("hostaudio: open_user called\n");
-#endif
-
-        state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-
-        if(state->fd >= 0) return(0);
-
-        printk("hostaudio_open_user failed to open '%s', errno = %d\n",
-	       dsp, errno);
-        
-        return(-errno); 
-}
-
-int hostaudio_release_user(struct hostaudio_state *state)
-{
-#ifdef DEBUG
-        printk("hostaudio: release called\n");
-#endif
-        if(state->fd >= 0){
-		close(state->fd);
-		state->fd=-1;
-        }
-
-        return(0);
-}
-
-/* /dev/mixer file operations */
-
-int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state, 
-				unsigned int cmd, unsigned long arg)
-{
-	int ret;
-#ifdef DEBUG
-        printk("hostmixer: ioctl_user called cmd = %u\n",cmd);
-#endif
-
-        ret = ioctl(state->fd, cmd, arg);
-	if(ret < 0) 
-		return(-errno);
-	return(ret);
-}
-
-int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w,
-			       char *mixer)
-{
-#ifdef DEBUG
-        printk("hostmixer: open_user called\n");
-#endif
-
-        state->fd = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
-
-        if(state->fd >= 0) return(0);
-
-        printk("hostaudio_open_mixdev_user failed to open '%s', errno = %d\n",
-	       mixer, errno);
-        
-        return(-errno); 
-}
-
-int hostmixer_release_mixdev_user(struct hostmixer_state *state)
-{
-#ifdef DEBUG
-        printk("hostmixer: release_user called\n");
-#endif
-
-        if(state->fd >= 0){
-		close(state->fd);
-		state->fd = -1;
-        }
-
-        return 0;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/drivers/line.c b/arch/um/drivers/line.c
--- a/arch/um/drivers/line.c	2003-06-11 12:33:07 -07:00
+++ b/arch/um/drivers/line.c	2004-08-24 02:08:18 -07:00
@@ -6,8 +6,8 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/list.h"
+#include "linux/interrupt.h"
 #include "linux/devfs_fs_kernel.h"
-#include "asm/irq.h"
 #include "asm/uaccess.h"
 #include "chan_kern.h"
 #include "irq_user.h"
@@ -16,38 +16,55 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "os.h"
+#include "irq_kern.h"
 
 #define LINE_BUFSIZE 4096
 
-void line_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct line *dev = data;
 
 	if(dev->count > 0) 
 		chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq, 
 			       dev);
+	return IRQ_HANDLED;
 }
 
-void line_timer_cb(void *arg)
+static void line_timer_cb(void *arg)
 {
 	struct line *dev = arg;
 
 	line_interrupt(dev->driver->read_irq, dev, NULL);
 }
 
-static void buffer_data(struct line *line, const char *buf, int len)
+static int write_room(struct line *dev)
 {
-	int end;
+	int n;
+
+	if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
+
+	n = dev->head - dev->tail;
+	if(n <= 0) n = LINE_BUFSIZE + n;
+	return(n - 1);
+}
+
+static int buffer_data(struct line *line, const char *buf, int len)
+{
+	int end, room;
 
 	if(line->buffer == NULL){
 		line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
 		if(line->buffer == NULL){
 			printk("buffer_data - atomic allocation failed\n");
-			return;
+			return(0);
 		}
 		line->head = line->buffer;
 		line->tail = line->buffer;
 	}
+
+	room = write_room(line);
+	len = (len > room) ? room : len;
+
 	end = line->buffer + LINE_BUFSIZE - line->tail;
 	if(len < end){
 		memcpy(line->tail, buf, len);
@@ -60,6 +77,8 @@
 		memcpy(line->buffer, buf, len);
 		line->tail = line->buffer + len;
 	}
+
+	return(len);
 }
 
 static int flush_buffer(struct line *line)
@@ -95,7 +114,7 @@
 	struct line *line;
 	char *new;
 	unsigned long flags;
-	int n, err, i;
+	int n, err, i, ret = 0;
 
 	if(tty->stopped) return 0;
 
@@ -104,9 +123,13 @@
 		if(new == NULL)
 			return(0);
 		n = copy_from_user(new, buf, len);
-		if(n == len)
-			return(-EFAULT);
 		buf = new;
+		if(n == len){
+			len = -EFAULT;
+			goto out_free;
+		}
+
+		len -= n;
 	}
 
 	i = tty->index;
@@ -115,41 +138,50 @@
 	down(&line->sem);
 	if(line->head != line->tail){
 		local_irq_save(flags);
-		buffer_data(line, buf, len);
+		ret += buffer_data(line, buf, len);
 		err = flush_buffer(line);
 		local_irq_restore(flags);
 		if(err <= 0)
-			goto out;
+			goto out_up;
 	}
 	else {
 		n = write_chan(&line->chan_list, buf, len, 
 			       line->driver->write_irq);
 		if(n < 0){
-			len = n;
-			goto out;
+			ret = n;
+			goto out_up;
 		}
-		if(n < len)
-			buffer_data(line, buf + n, len - n);
+
+		len -= n;
+		ret += n;
+		if(len > 0)
+			ret += buffer_data(line, buf + n, len);
 	}
- out:
+ out_up:
 	up(&line->sem);
-	return(len);
+ out_free:
+	if(from_user)
+		kfree(buf);
+	return(ret);
 }
 
-void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_write_interrupt(int irq, void *data,
+					struct pt_regs *unused)
 {
 	struct line *dev = data;
 	struct tty_struct *tty = dev->tty;
 	int err;
 
 	err = flush_buffer(dev);
-	if(err == 0) return;
+	if(err == 0)
+		return(IRQ_NONE);
 	else if(err < 0){
 		dev->head = dev->buffer;
 		dev->tail = dev->buffer;
 	}
 
-	if(tty == NULL) return;
+	if(tty == NULL)
+		return(IRQ_NONE);
 
 	if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
 	   (tty->ldisc.write_wakeup != NULL))
@@ -161,21 +193,9 @@
 	 * writes.
 	 */
 
-	if (waitqueue_active(&tty->write_wait))
+	if(waitqueue_active(&tty->write_wait))
 		wake_up_interruptible(&tty->write_wait);
-
-}
-
-int line_write_room(struct tty_struct *tty)
-{
-	struct line *dev = tty->driver_data;
-	int n;
-
-	if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
-
-	n = dev->head - dev->tail;
-	if(n <= 0) n = LINE_BUFSIZE + n;
-	return(n - 1);
+	return(IRQ_HANDLED);
 }
 
 int line_setup_irq(int fd, int input, int output, void *data)
@@ -305,7 +325,7 @@
 		if(*end != '='){
 			printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 
 			       init);
-			return(1);
+			return(0);
 		}
 		init = end;
 	}
@@ -313,12 +333,12 @@
 	if((n >= 0) && (n >= num)){
 		printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
 		       n, num);
-		return(1);
+		return(0);
 	}
 	else if(n >= 0){
 		if(lines[n].count > 0){
 			printk("line_setup - device %d is open\n", n);
-			return(1);
+			return(0);
 		}
 		if(lines[n].init_pri <= INIT_ONE){
 			lines[n].init_pri = INIT_ONE;
@@ -332,7 +352,7 @@
 	else if(!all_allowed){
 		printk("line_setup - can't configure all devices from "
 		       "mconsole\n");
-		return(1);
+		return(0);
 	}
 	else {
 		for(i = 0; i < num; i++){
@@ -346,7 +366,7 @@
 			}
 		}
 	}
-	return(0);
+	return(1);
 }
 
 int line_config(struct line *lines, int num, char *str)
@@ -357,7 +377,7 @@
 		printk("line_config - uml_strdup failed\n");
 		return(-ENOMEM);
 	}
-	return(line_setup(lines, num, new, 0));
+	return(!line_setup(lines, num, new, 0));
 }
 
 int line_get_config(char *name, struct line *lines, int num, char *str, 
@@ -369,7 +389,7 @@
 
 	dev = simple_strtoul(name, &end, 0);
 	if((*end != '\0') || (end == name)){
-		*error_out = "line_setup failed to parse device number";
+		*error_out = "line_get_config failed to parse device number";
 		return(0);
 	}
 
@@ -379,15 +399,15 @@
 	}
 
 	line = &lines[dev];
+
 	down(&line->sem);
-	
 	if(!line->valid)
 		CONFIG_CHUNK(str, size, n, "none", 1);
 	else if(line->count == 0)
 		CONFIG_CHUNK(str, size, n, line->init_str, 1);
 	else n = chan_config_string(&line->chan_list, str, size, error_out);
-
 	up(&line->sem);
+
 	return(n);
 }
 
@@ -396,7 +416,14 @@
 	char config[sizeof("conxxxx=none\0")];
 
 	sprintf(config, "%s=none", str);
-	return(line_setup(lines, num, config, 0));
+	return(!line_setup(lines, num, config, 0));
+}
+
+int line_write_room(struct tty_struct *tty)
+{
+	struct line *dev = tty->driver_data;
+
+	return(write_room(dev));
 }
 
 struct tty_driver *line_register_devfs(struct lines *set,
@@ -412,7 +439,8 @@
 		return NULL;
 
 	driver->driver_name = line_driver->name;
-	driver->name = line_driver->devfs_name;
+	driver->name = line_driver->device_name;
+	driver->devfs_name = line_driver->devfs_name;
 	driver->major = line_driver->major;
 	driver->minor_start = line_driver->minor_start;
 	driver->type = line_driver->type;
@@ -432,7 +460,7 @@
 
 	for(i = 0; i < nlines; i++){
 		if(!lines[i].valid) 
-			tty_unregister_devfs(driver, i);
+			tty_unregister_device(driver, i);
 	}
 
 	mconsole_register_dev(&line_driver->mc);
@@ -465,24 +493,25 @@
 	struct line *line;
 };
 
-void winch_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct winch *winch = data;
 	struct tty_struct *tty;
 	int err;
 	char c;
 
-	err = generic_read(winch->fd, &c, NULL);
-	if(err < 0){
-		if(err != -EAGAIN){
-			printk("winch_interrupt : read failed, errno = %d\n", 
-			       -err);
-			printk("fd %d is losing SIGWINCH support\n", 
-			       winch->tty_fd);
-			free_irq(irq, data);
-			return;
+	if(winch->fd != -1){
+		err = generic_read(winch->fd, &c, NULL);
+		if(err < 0){
+			if(err != -EAGAIN){
+				printk("winch_interrupt : read failed, "
+				       "errno = %d\n", -err);
+				printk("fd %d is losing SIGWINCH support\n",
+				       winch->tty_fd);
+				return(IRQ_HANDLED);
+			}
+			goto out;
 		}
-		goto out;
 	}
 	tty = winch->line->tty;
 	if(tty != NULL){
@@ -492,7 +521,9 @@
 		kill_pg(tty->pgrp, SIGWINCH, 1);
 	}
  out:
-	reactivate_fd(winch->fd, WINCH_IRQ);
+	if(winch->fd != -1)
+		reactivate_fd(winch->fd, WINCH_IRQ);
+	return(IRQ_HANDLED);
 }
 
 DECLARE_MUTEX(winch_handler_sem);
@@ -529,7 +560,10 @@
 
 	list_for_each(ele, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
-		close(winch->fd);
+		if(winch->fd != -1){
+			deactivate_fd(winch->fd, WINCH_IRQ);
+			os_close_file(winch->fd);
+		}
 		if(winch->pid != -1) 
 			os_kill_process(winch->pid, 1);
 	}
diff -Nru a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
--- a/arch/um/drivers/mcast_user.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/mcast_user.c	2004-08-24 02:08:18 -07:00
@@ -23,6 +23,7 @@
 #include "kern_util.h"
 #include "user_util.h"
 #include "user.h"
+#include "os.h"
 
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
@@ -62,7 +63,8 @@
 		goto out;
 	}
 
-	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd < 0){
 		printk("mcast_open : data socket failed, errno = %d\n", 
 		       errno);
 		fd = -ENOMEM;
@@ -72,7 +74,7 @@
 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
 		printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -82,7 +84,7 @@
 		       sizeof(pri->ttl)) < 0) {
 		printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -91,7 +93,7 @@
 	if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
 		printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -99,7 +101,7 @@
 	/* bind socket to mcast address */
 	if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
 		printk("mcast_open : data bind failed, errno = %d\n", errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}		
@@ -115,7 +117,7 @@
 		       "interface on the host.\n");
 		printk("eth0 should be configured in order to use the "
 		       "multicast transport.\n");
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 	}
 
@@ -137,7 +139,7 @@
 			errno);
 	}
 
-	close(fd);
+	os_close_file(fd);
 }
 
 int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
diff -Nru a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
--- a/arch/um/drivers/mconsole_kern.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/mconsole_kern.c	2004-08-24 02:08:18 -07:00
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -15,6 +15,9 @@
 #include "linux/sysrq.h"
 #include "linux/workqueue.h"
 #include "linux/module.h"
+#include "linux/file.h"
+#include "linux/fs.h"
+#include "linux/namei.h"
 #include "linux/proc_fs.h"
 #include "asm/irq.h"
 #include "asm/uaccess.h"
@@ -27,6 +30,7 @@
 #include "init.h"
 #include "os.h"
 #include "umid.h"
+#include "irq_kern.h"
 
 static int do_unlink_socket(struct notifier_block *notifier, 
 			    unsigned long what, void *data)
@@ -67,7 +71,7 @@
 
 DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
 
-void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int fd;
 	struct mconsole_entry *new;
@@ -75,9 +79,10 @@
 
 	fd = (int) dev_id;
 	while (mconsole_get_request(fd, &req)){
-		if(req.cmd->as_interrupt) (*req.cmd->handler)(&req);
+		if(req.cmd->context == MCONSOLE_INTR)
+			(*req.cmd->handler)(&req);
 		else {
-			new = kmalloc(sizeof(req), GFP_ATOMIC);
+			new = kmalloc(sizeof(*new), GFP_ATOMIC);
 			if(new == NULL)
 				mconsole_reply(&req, "Out of memory", 1, 0);
 			else {
@@ -88,6 +93,7 @@
 	}
 	if(!list_empty(&mc_requests)) schedule_work(&mconsole_work);
 	reactivate_fd(fd, MCONSOLE_IRQ);
+	return(IRQ_HANDLED);
 }
 
 void mconsole_version(struct mc_request *req)
@@ -100,20 +106,109 @@
 	mconsole_reply(req, version, 0, 0);
 }
 
+void mconsole_log(struct mc_request *req)
+{
+	int len;
+	char *ptr = req->request.data;
+
+	ptr += strlen("log ");
+
+	len = req->len - (ptr - req->request.data);
+	printk("%.*s", len, ptr);
+	mconsole_reply(req, "", 0, 0);
+}
+
+void mconsole_proc(struct mc_request *req)
+{
+	struct nameidata nd;
+	struct file_system_type *proc;
+	struct super_block *super;
+	struct file *file;
+	int n, err;
+	char *ptr = req->request.data, *buf;
+
+	ptr += strlen("proc");
+	while(isspace(*ptr)) ptr++;
+
+	proc = get_fs_type("proc");
+	if(proc == NULL){
+		mconsole_reply(req, "procfs not registered", 1, 0);
+		goto out;
+	}
+
+	super = (*proc->get_sb)(proc, 0, NULL, NULL);
+	put_filesystem(proc);
+	if(super == NULL){
+		mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
+		goto out;
+	}
+	up_write(&super->s_umount);
+
+	nd.dentry = super->s_root;
+	nd.mnt = NULL;
+	nd.flags = O_RDONLY + 1;
+	nd.last_type = LAST_ROOT;
+
+	err = link_path_walk(ptr, &nd);
+	if(err){
+		mconsole_reply(req, "Failed to look up file", 1, 0);
+		goto out_kill;
+	}
+
+	file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+	if(IS_ERR(file)){
+		mconsole_reply(req, "Failed to open file", 1, 0);
+		goto out_kill;
+	}
+
+	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if(buf == NULL){
+		mconsole_reply(req, "Failed to allocate buffer", 1, 0);
+		goto out_fput;
+	}
+
+	if((file->f_op != NULL) && (file->f_op->read != NULL)){
+		do {
+			n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
+						&file->f_pos);
+			if(n >= 0){
+				buf[n] = '\0';
+				mconsole_reply(req, buf, 0, (n > 0));
+			}
+			else {
+				mconsole_reply(req, "Read of file failed",
+					       1, 0);
+				goto out_free;
+			}
+		} while(n > 0);
+	}
+	else mconsole_reply(req, "", 0, 0);
+
+ out_free:
+	kfree(buf);
+ out_fput:
+	fput(file);
+ out_kill:
+	deactivate_super(super);
+ out: ;
+}
+
 #define UML_MCONSOLE_HELPTEXT \
-"Commands:
-    version - Get kernel version
-    help - Print this message
-    halt - Halt UML
-    reboot - Reboot UML
-    config <dev>=<config> - Add a new device to UML; 
-	same syntax as command line
-    config <dev> - Query the configuration of a device
-    remove <dev> - Remove a device from UML
-    sysrq <letter> - Performs the SysRq action controlled by the letter
-    cad - invoke the Ctl-Alt-Del handler
-    stop - pause the UML; it will do nothing until it receives a 'go'
-    go - continue the UML after a 'stop'
+"Commands: \n\
+    version - Get kernel version \n\
+    help - Print this message \n\
+    halt - Halt UML \n\
+    reboot - Reboot UML \n\
+    config <dev>=<config> - Add a new device to UML;  \n\
+	same syntax as command line \n\
+    config <dev> - Query the configuration of a device \n\
+    remove <dev> - Remove a device from UML \n\
+    sysrq <letter> - Performs the SysRq action controlled by the letter \n\
+    cad - invoke the Ctl-Alt-Del handler \n\
+    stop - pause the UML; it will do nothing until it receives a 'go' \n\
+    go - continue the UML after a 'stop' \n\
+    log <string> - make UML enter <string> into the kernel log\n\
+    proc <file> - returns the contents of the UML's /proc/<file>\n\
 "
 
 void mconsole_help(struct mc_request *req)
@@ -302,7 +397,7 @@
 	if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
 	snprintf(mconsole_socket_name, sizeof(file), "%s", file);
 
-	sock = create_unix_socket(file, sizeof(file));
+	sock = os_create_unix_socket(file, sizeof(file), 1);
 	if (sock < 0){
 		printk("Failed to initialize management console\n");
 		return(1);
@@ -344,11 +439,16 @@
 	if(buf == NULL) 
 		return(-ENOMEM);
 
-	if(copy_from_user(buf, buffer, count))
-		return(-EFAULT);
+	if(copy_from_user(buf, buffer, count)){
+		count = -EFAULT;
+		goto out;
+	}
+
 	buf[count] = '\0';
 
 	mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count);
+ out:
+	kfree(buf);
 	return(count);
 }
 
diff -Nru a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
--- a/arch/um/drivers/mconsole_user.c	2002-10-14 06:53:49 -07:00
+++ b/arch/um/drivers/mconsole_user.c	2004-08-24 02:08:18 -07:00
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -18,16 +18,18 @@
 #include "umid.h"
 
 static struct mconsole_command commands[] = {
-	{ "version", mconsole_version, 1 },
-	{ "halt", mconsole_halt, 0 },
-	{ "reboot", mconsole_reboot, 0 },
-	{ "config", mconsole_config, 0 },
-	{ "remove", mconsole_remove, 0 },
-	{ "sysrq", mconsole_sysrq, 1 },
-	{ "help", mconsole_help, 1 },
-	{ "cad", mconsole_cad, 1 },
-	{ "stop", mconsole_stop, 0 },
-	{ "go", mconsole_go, 1 },
+	{ "version", mconsole_version, MCONSOLE_INTR },
+	{ "halt", mconsole_halt, MCONSOLE_PROC },
+	{ "reboot", mconsole_reboot, MCONSOLE_PROC },
+	{ "config", mconsole_config, MCONSOLE_PROC },
+	{ "remove", mconsole_remove, MCONSOLE_PROC },
+	{ "sysrq", mconsole_sysrq, MCONSOLE_INTR },
+	{ "help", mconsole_help, MCONSOLE_INTR },
+	{ "cad", mconsole_cad, MCONSOLE_INTR },
+	{ "stop", mconsole_stop, MCONSOLE_PROC },
+	{ "go", mconsole_go, MCONSOLE_INTR },
+	{ "log", mconsole_log, MCONSOLE_INTR },
+	{ "proc", mconsole_proc, MCONSOLE_PROC },
 };
 
 /* Initialized in mconsole_init, which is an initcall */
@@ -139,6 +141,7 @@
 		memcpy(reply.data, str, len);
 		reply.data[len] = '\0';
 		total -= len;
+		str += len;
 		reply.len = len + 1;
 
 		len = sizeof(reply) + reply.len - sizeof(reply.data);
diff -Nru a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
--- a/arch/um/drivers/mmapper_kern.c	2003-05-07 08:47:29 -07:00
+++ b/arch/um/drivers/mmapper_kern.c	2004-08-24 02:08:18 -07:00
@@ -120,7 +120,10 @@
 	printk(KERN_INFO "Mapper v0.1\n");
 
 	v_buf = (char *) find_iomem("mmapper", &mmapper_size);
-	if(mmapper_size == 0) return(0);
+	if(mmapper_size == 0){
+		printk(KERN_ERR "mmapper_init - find_iomem failed\n");
+		return(0);
+	}
 
 	p_buf = __pa(v_buf);
 
diff -Nru a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
--- a/arch/um/drivers/net_kern.c	2004-05-10 04:25:54 -07:00
+++ b/arch/um/drivers/net_kern.c	2004-08-24 02:08:18 -07:00
@@ -26,6 +26,7 @@
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
 LIST_HEAD(opened);
@@ -37,7 +38,8 @@
 	struct sk_buff *skb;
 
 	/* If we can't allocate memory, try again next round. */
-	if ((skb = dev_alloc_skb(dev->mtu)) == NULL) {
+	skb = dev_alloc_skb(dev->mtu);
+	if (skb == NULL) {
 		lp->stats.rx_dropped++;
 		return 0;
 	}
@@ -61,14 +63,14 @@
 	return pkt_len;
 }
 
-void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct uml_net_private *lp = dev->priv;
 	int err;
 
 	if(!netif_running(dev))
-		return;
+		return(IRQ_NONE);
 
 	spin_lock(&lp->lock);
 	while((err = uml_net_rx(dev)) > 0) ;
@@ -83,6 +85,7 @@
 
  out:
 	spin_unlock(&lp->lock);
+	return(IRQ_HANDLED);
 }
 
 static int uml_net_open(struct net_device *dev)
@@ -250,37 +253,6 @@
 #endif
 }
 
-/*
- * default do nothing hard header packet routines for struct net_device init.
- * real ethernet transports will overwrite with real routines.
- */
-static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
-                 unsigned short type, void *daddr, void *saddr, unsigned len)
-{
-	return(0); /* no change */
-}
-
-static int uml_net_rebuild_header(struct sk_buff *skb)
-{
-	return(0); /* ignore */ 
-}
-
-static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
-{
-	return(-1); /* fail */
-}
-
-static void uml_net_header_cache_update(struct hh_cache *hh,
-                 struct net_device *dev, unsigned char * haddr)
-{
-	/* ignore */
-}
-
-static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
-{
-	return(0); /* nothing */
-}
-
 static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
 static struct list_head devices = LIST_HEAD_INIT(devices);
 
@@ -290,7 +262,7 @@
 	struct uml_net *device;
 	struct net_device *dev;
 	struct uml_net_private *lp;
-	int err, size;
+	int save, err, size;
 
 	size = transport->private_size + sizeof(struct uml_net_private) + 
 		sizeof(((struct uml_net_private *) 0)->user);
@@ -332,12 +304,6 @@
 	snprintf(dev->name, sizeof(dev->name), "eth%d", n);
 	device->dev = dev;
 
-        dev->hard_header = uml_net_hard_header;
-        dev->rebuild_header = uml_net_rebuild_header;
-        dev->hard_header_cache = uml_net_header_cache;
-        dev->header_cache_update= uml_net_header_cache_update;
-        dev->hard_header_parse = uml_net_header_parse;
-
 	(*transport->kern->init)(dev, init);
 
 	dev->mtu = transport->user->max_packet;
@@ -364,21 +330,29 @@
 	}
 	lp = dev->priv;
 
-	INIT_LIST_HEAD(&lp->list);
-	spin_lock_init(&lp->lock);
-	lp->dev = dev;
-	lp->fd = -1;
-	lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 };
-	lp->have_mac = device->have_mac;
-	lp->protocol = transport->kern->protocol;
-	lp->open = transport->user->open;
-	lp->close = transport->user->close;
-	lp->remove = transport->user->remove;
-	lp->read = transport->kern->read;
-	lp->write = transport->kern->write;
-	lp->add_address = transport->user->add_address;
-	lp->delete_address = transport->user->delete_address;
-	lp->set_mtu = transport->user->set_mtu;
+	/* lp.user is the first four bytes of the transport data, which
+	 * has already been initialized.  This structure assignment will
+	 * overwrite that, so we make sure that .user gets overwritten with
+	 * what it already has.
+	 */
+	save = lp->user[0];
+	*lp = ((struct uml_net_private)
+		{ .list  		= LIST_HEAD_INIT(lp->list),
+		  .lock 		= SPIN_LOCK_UNLOCKED,
+		  .dev 			= dev,
+		  .fd 			= -1,
+		  .mac 			= { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
+		  .have_mac 		= device->have_mac,
+		  .protocol 		= transport->kern->protocol,
+		  .open 		= transport->user->open,
+		  .close 		= transport->user->close,
+		  .remove 		= transport->user->remove,
+		  .read 		= transport->kern->read,
+		  .write 		= transport->kern->write,
+		  .add_address 		= transport->user->add_address,
+		  .delete_address  	= transport->user->delete_address,
+		  .set_mtu 		= transport->user->set_mtu,
+		  .user  		= { save } });
 
 	init_timer(&lp->tl);
 	lp->tl.function = uml_net_user_timer_expire;
@@ -611,7 +585,8 @@
 	unregister_netdev(dev);
 
 	list_del(&device->list);
-	free_netdev(device);
+	kfree(device);
+	free_netdev(dev);
 	return(0);
 }
 
diff -Nru a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
--- a/arch/um/drivers/net_user.c	2002-10-02 08:33:44 -07:00
+++ b/arch/um/drivers/net_user.c	2004-08-24 02:08:27 -07:00
@@ -26,8 +26,7 @@
 	if(gate_addr == NULL) return(0);
 	if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], 
 		  &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
-		printk("Invalid tap IP address - '%s'\n", 
-		       gate_addr);
+		printk("Invalid tap IP address - '%s'\n", gate_addr);
 		return(-EINVAL);
 	}
 	return(0);
@@ -60,18 +59,18 @@
 	}
 		
 	*output = '\0';
-	if(read(fd, &remain, sizeof(remain)) != sizeof(remain)){
-		printk("read_output - read of length failed, errno = %d\n",
-		       errno);
+	n = os_read_file(fd, &remain, sizeof(remain));
+	if(n != sizeof(remain)){
+		printk("read_output - read of length failed, err = %d\n", -n);
 		return;
 	}
 
 	while(remain != 0){
 		n = (remain < len) ? remain : len;
-		actual = read(fd, output, n);
+		actual = os_read_file(fd, output, n);
 		if(actual != n){
 			printk("read_output - read of data failed, "
-			       "errno = %d\n", errno);
+			       "err = %d\n", -actual);
 			return;
 		}
 		remain -= actual;
@@ -83,13 +82,12 @@
 {
 	int n;
 
-	while(((n = read(fd,  buf,  len)) < 0) && (errno == EINTR)) ;
+	n = os_read_file(fd,  buf,  len);
 
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-ENOTCONN);
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-ENOTCONN);
 	return(n);
 }
 
@@ -112,13 +110,13 @@
 {
 	int n;
 
-	while(((n = write(fd, buf, len)) < 0) && (errno == EINTR)) ;
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-ENOTCONN);
-	return(n);	
+	n = os_write_file(fd, buf, len);
+
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-ENOTCONN);
+	return(n);
 }
 
 int net_send(int fd, void *buf, int len)
@@ -157,7 +155,7 @@
 {
 	struct change_pre_exec_data *data = arg;
 
-	close(data->close_me);
+	os_close_file(data->close_me);
 	dup2(data->stdout, 1);
 }
 
@@ -167,17 +165,18 @@
 	struct change_pre_exec_data pe_data;
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("change_tramp - pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("change_tramp - pipe failed, err = %d\n", -err);
 		return(err);
 	}
 	pe_data.close_me = fds[0];
 	pe_data.stdout = fds[1];
 	pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
 
-	close(fds[1]);
+	os_close_file(fds[1]);
 	read_output(fds[0], output, output_len);
-	waitpid(pid, NULL, 0);	
+
+	CATCH_EINTR(err = waitpid(pid, NULL, 0));
 	return(pid);
 }
 
diff -Nru a/arch/um/drivers/null.c b/arch/um/drivers/null.c
--- a/arch/um/drivers/null.c	2002-12-28 18:20:34 -08:00
+++ b/arch/um/drivers/null.c	2004-08-24 02:08:18 -07:00
@@ -5,7 +5,6 @@
 
 #include <stdlib.h>
 #include <errno.h>
-#include <fcntl.h>
 #include "chan_user.h"
 #include "os.h"
 
diff -Nru a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
--- a/arch/um/drivers/port_kern.c	2003-02-05 20:16:01 -08:00
+++ b/arch/um/drivers/port_kern.c	2004-08-24 02:08:18 -07:00
@@ -6,6 +6,7 @@
 #include "linux/list.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
+#include "linux/interrupt.h"
 #include "linux/irq.h"
 #include "linux/spinlock.h"
 #include "linux/errno.h"
@@ -14,6 +15,7 @@
 #include "kern_util.h"
 #include "kern.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "port.h"
 #include "init.h"
 #include "os.h"
@@ -38,21 +40,21 @@
 struct connection {
 	struct list_head list;
 	int fd;
- 	int helper_pid;
+	int helper_pid;
 	int socket[2];
 	int telnetd_pid;
 	struct port_list *port;
 };
 
-static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct connection *conn = data;
 	int fd;
 
- 	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
+	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
 	if(fd < 0){
 		if(fd == -EAGAIN)
-			return;
+			return(IRQ_NONE);
 
 		printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", 
 		       -fd);
@@ -65,6 +67,7 @@
 	list_add(&conn->list, &conn->port->connections);
 
 	up(&conn->port->sem);
+	return(IRQ_HANDLED);
 }
 
 static int port_accept(struct port_list *port)
@@ -102,8 +105,7 @@
 	}
 
 	list_add(&conn->list, &port->pending);
-	ret = 1;
-	goto out;
+	return(1);
 
  out_free:
 	kfree(conn);
@@ -138,12 +140,13 @@
 
 DECLARE_WORK(port_work, port_work_proc, NULL);
 
-static void port_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct port_list *port = data;
 
 	port->has_connection = 1;
 	schedule_work(&port_work);
+	return(IRQ_HANDLED);
 } 
 
 void *port_data(int port_num)
diff -Nru a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
--- a/arch/um/drivers/port_user.c	2003-02-05 20:16:02 -08:00
+++ b/arch/um/drivers/port_user.c	2004-08-24 02:08:18 -07:00
@@ -47,10 +47,12 @@
 		return(NULL);
 	}
 
-	if((kern_data = port_data(port)) == NULL) 
+	kern_data = port_data(port);
+	if(kern_data == NULL)
 		return(NULL);
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) 
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL)
 		goto err;
 
 	*data = ((struct port_chan) { .raw  		= opts->raw,
@@ -90,7 +92,7 @@
 	struct port_chan *data = d;
 
 	port_remove_dev(data->kernel_data);
-	close(fd);
+	os_close_file(fd);
 }
 
 int port_console_write(int fd, const char *buf, int n, void *d)
@@ -130,11 +132,15 @@
 		goto out;
 	}
   
-	if((listen(fd, 1) < 0) || (os_set_fd_block(fd, 0))){
+	if(listen(fd, 1) < 0){
 		err = -errno;
 		goto out;
 	}
 
+	err = os_set_fd_block(fd, 0);
+	if(err < 0)
+		goto out;
+
 	return(fd);
  out:
 	os_close_file(fd);
@@ -153,10 +159,10 @@
 	dup2(data->sock_fd, 0);
 	dup2(data->sock_fd, 1);
 	dup2(data->sock_fd, 2);
-	close(data->sock_fd);
+	os_close_file(data->sock_fd);
 	dup2(data->pipe_fd, 3);
 	os_shutdown_socket(3, 1, 0);
-	close(data->pipe_fd);
+	os_close_file(data->pipe_fd);
 }
 
 int port_connection(int fd, int *socket, int *pid_out)
@@ -166,11 +172,12 @@
 			 "/usr/lib/uml/port-helper", NULL };
 	struct port_pre_exec_data data;
 
-	if((new = os_accept_connection(fd)) < 0)
-		return(-errno);
+	new = os_accept_connection(fd);
+	if(new < 0)
+		return(new);
 
 	err = os_pipe(socket, 0, 0);
-	if(err) 
+	if(err < 0)
 		goto out_close;
 
 	data = ((struct port_pre_exec_data)
@@ -186,11 +193,11 @@
 
  out_shutdown:
 	os_shutdown_socket(socket[0], 1, 1);
-	close(socket[0]);
+	os_close_file(socket[0]);
 	os_shutdown_socket(socket[1], 1, 1);	
-	close(socket[1]);
+	os_close_file(socket[1]);
  out_close:
-	close(new);
+	os_close_file(new);
 	return(err);
 }
 
diff -Nru a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
--- a/arch/um/drivers/pty.c	2002-12-29 15:39:15 -08:00
+++ b/arch/um/drivers/pty.c	2004-08-24 02:08:18 -07:00
@@ -7,12 +7,12 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <termios.h>
 #include "chan_user.h"
 #include "user.h"
 #include "user_util.h"
 #include "kern_util.h"
+#include "os.h"
 
 struct pty_chan {
 	void (*announce)(char *dev_name, int dev);
@@ -26,7 +26,8 @@
 {
 	struct pty_chan *data;
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct pty_chan) { .announce  	= opts->announce, 
 				     .dev  		= device,
 				     .raw  		= opts->raw });
@@ -39,7 +40,8 @@
 	char *dev;
 	int fd;
 
-	if((fd = get_pty()) < 0){
+	fd = get_pty();
+	if(fd < 0){
 		printk("open_pts : Failed to open pts\n");
 		return(-errno);
 	}
@@ -57,29 +59,27 @@
 
 int getmaster(char *line)
 {
-	struct stat stb;
 	char *pty, *bank, *cp;
-	int master;
+	int master, err;
 
 	pty = &line[strlen("/dev/ptyp")];
 	for (bank = "pqrs"; *bank; bank++) {
 		line[strlen("/dev/pty")] = *bank;
 		*pty = '0';
-		if (stat(line, &stb) < 0)
+		if (os_stat_file(line, NULL) < 0)
 			break;
 		for (cp = "0123456789abcdef"; *cp; cp++) {
 			*pty = *cp;
-			master = open(line, O_RDWR);
+			master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
 			if (master >= 0) {
 				char *tp = &line[strlen("/dev/")];
-				int ok;
 
 				/* verify slave side is usable */
 				*tp = 't';
-				ok = access(line, R_OK|W_OK) == 0;
+				err = os_access(line, OS_ACC_RW_OK);
 				*tp = 'p';
-				if (ok) return(master);
-				(void) close(master);
+				if(err == 0) return(master);
+				(void) os_close_file(master);
 			}
 		}
 	}
diff -Nru a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
--- a/arch/um/drivers/slip_user.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/slip_user.c	2004-08-24 02:08:27 -07:00
@@ -4,11 +4,9 @@
 #include <stddef.h>
 #include <sched.h>
 #include <string.h>
-#include <sys/fcntl.h>
-#include <sys/errno.h>
+#include <errno.h>
 #include <sys/termios.h>
 #include <sys/wait.h>
-#include <sys/ioctl.h>
 #include <sys/signal.h>
 #include "user_util.h"
 #include "kern_util.h"
@@ -65,9 +63,9 @@
 {
 	struct slip_pre_exec_data *data = arg;
 
-	if(data->stdin != -1) dup2(data->stdin, 0);
+	if(data->stdin >= 0) dup2(data->stdin, 0);
 	dup2(data->stdout, 1);
-	if(data->close_me != -1) close(data->close_me);
+	if(data->close_me >= 0) os_close_file(data->close_me);
 }
 
 static int slip_tramp(char **argv, int fd)
@@ -77,8 +75,8 @@
 	int status, pid, fds[2], err, output_len;
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("slip_tramp : pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("slip_tramp : pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -96,16 +94,18 @@
 			printk("slip_tramp : failed to allocate output "
 			       "buffer\n");
 
-		close(fds[1]);
+		os_close_file(fds[1]);
 		read_output(fds[0], output, output_len);
 		if(output != NULL){
 			printk("%s", output);
 			kfree(output);
 		}
-		if(waitpid(pid, &status, 0) < 0) err = errno;
+		CATCH_EINTR(err = waitpid(pid, &status, 0));
+		if(err < 0)
+			err = errno;
 		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
 			printk("'%s' didn't exit with status 0\n", argv[0]);
-			err = EINVAL;
+			err = -EINVAL;
 		}
 	}
 	return(err);
@@ -118,15 +118,17 @@
 	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
 	char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, 
 			 NULL };
-	int sfd, mfd, disc, sencap, err;
+	int sfd, mfd, err;
 
-	if((mfd = get_pty()) < 0){
-		printk("umn : Failed to open pty\n");
-		return(-1);
-	}
-	if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){
-		printk("Couldn't open tty for slip line\n");
-		return(-1);
+	mfd = get_pty();
+	if(mfd < 0){
+		printk("umn : Failed to open pty, err = %d\n", -mfd);
+		return(mfd);
+	}
+	sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
+	if(sfd < 0){
+		printk("Couldn't open tty for slip line, err = %d\n", -sfd);
+		return(sfd);
 	}
 	if(set_up_tty(sfd)) return(-1);
 	pri->slave = sfd;
@@ -138,28 +140,23 @@
 
 		err = slip_tramp(argv, sfd);
 
-		if(err != 0){
-			printk("slip_tramp failed - errno = %d\n", err);
-			return(-err);
-		}
-		if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){
-			printk("SIOCGIFNAME failed, errno = %d\n", errno);
-			return(-errno);
+		if(err < 0){
+			printk("slip_tramp failed - err = %d\n", -err);
+			return(err);
+		}
+		err = os_get_ifname(pri->slave, pri->name);
+		if(err < 0){
+			printk("get_ifname failed, err = %d\n", -err);
+			return(err);
 		}
 		iter_addresses(pri->dev, open_addr, pri->name);
 	}
 	else {
-		disc = N_SLIP;
-		if(ioctl(sfd, TIOCSETD, &disc) < 0){
-			printk("Failed to set slip line discipline - "
-			       "errno = %d\n", errno);
-			return(-errno);
-		}
-		sencap = 0;
-		if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){
-			printk("Failed to set slip encapsulation - "
-			       "errno = %d\n", errno);
-			return(-errno);
+		err = os_set_slip(sfd);
+		if(err < 0){
+			printk("Failed to set slip discipline encapsulation - "
+			       "err = %d\n", -err);
+			return(err);
 		}
 	}
 	return(mfd);
@@ -181,9 +178,9 @@
 	err = slip_tramp(argv, -1);
 
 	if(err != 0)
-		printk("slip_tramp failed - errno = %d\n", err);
-	close(fd);
-	close(pri->slave);
+		printk("slip_tramp failed - errno = %d\n", -err);
+	os_close_file(fd);
+	os_close_file(pri->slave);
 	pri->slave = -1;
 }
 
@@ -243,7 +240,7 @@
 {
 	struct slip_data *pri = data;
 
-	if(pri->slave == -1) return;
+	if(pri->slave < 0) return;
 	open_addr(addr, netmask, pri->name);
 }
 
@@ -252,7 +249,7 @@
 {
 	struct slip_data *pri = data;
 
-	if(pri->slave == -1) return;
+	if(pri->slave < 0) return;
 	close_addr(addr, netmask, pri->name);
 }
 
diff -Nru a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
--- a/arch/um/drivers/slirp_user.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/slirp_user.c	2004-08-24 02:08:27 -07:00
@@ -4,8 +4,7 @@
 #include <stddef.h>
 #include <sched.h>
 #include <string.h>
-#include <sys/fcntl.h>
-#include <sys/errno.h>
+#include <errno.h>
 #include <sys/wait.h>
 #include <sys/signal.h>
 #include "user_util.h"
@@ -48,15 +47,15 @@
 
 	return(pid);
 }
- 
+
+/* XXX This is just a trivial wrapper around os_pipe */
 static int slirp_datachan(int *mfd, int *sfd)
 {
 	int fds[2], err;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("slirp_datachan: Failed to open pipe, errno = %d\n",
-		       -err);
+	if(err < 0){
+		printk("slirp_datachan: Failed to open pipe, err = %d\n", -err);
 		return(err);
 	}
 
@@ -77,7 +76,7 @@
 	pid = slirp_tramp(pri->argw.argv, sfd);
 
 	if(pid < 0){
-		printk("slirp_tramp failed - errno = %d\n", pid);
+		printk("slirp_tramp failed - errno = %d\n", -pid);
 		os_close_file(sfd);	
 		os_close_file(mfd);	
 		return(pid);
@@ -97,8 +96,8 @@
 	struct slirp_data *pri = data;
 	int status,err;
 
-	close(fd);
-	close(pri->slave);
+	os_close_file(fd);
+	os_close_file(pri->slave);
 
 	pri->slave = -1;
 
@@ -114,13 +113,13 @@
 	}
 #endif
 
-	err = waitpid(pri->pid, &status, WNOHANG);
-	if(err<0) {
+	CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG));
+	if(err < 0) {
 		printk("slirp_close: waitpid returned %d\n", errno);
 		return;
 	}
 
-	if(err==0) {
+	if(err == 0) {
 		printk("slirp_close: process %d has not exited\n");
 		return;
 	}
diff -Nru a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
--- a/arch/um/drivers/ssl.c	2003-06-11 12:33:07 -07:00
+++ b/arch/um/drivers/ssl.c	2004-08-24 02:08:18 -07:00
@@ -10,6 +10,7 @@
 #include "linux/major.h"
 #include "linux/mm.h"
 #include "linux/init.h"
+#include "linux/console.h"
 #include "asm/termbits.h"
 #include "asm/irq.h"
 #include "line.h"
@@ -53,8 +54,9 @@
 
 static struct line_driver driver = {
 	.name 			= "UML serial line",
-	.devfs_name 		= "tts/%d",
-	.major 			= TTYAUX_MAJOR,
+	.device_name 		= "ttS",
+	.devfs_name 		= "tts/",
+	.major 			= TTY_MAJOR,
 	.minor_start 		= 64,
 	.type 		 	= TTY_DRIVER_TYPE_SERIAL,
 	.subtype 	 	= 0,
@@ -149,6 +151,9 @@
 	case TCSETSW:
 	case TCGETA:
 	case TIOCMGET:
+	case TCSBRK:
+	case TCSBRKP:
+	case TIOCMSET:
 		ret = -ENOIOCTLCMD;
 		break;
 	default:
@@ -212,6 +217,37 @@
  */
 static int ssl_init_done = 0;
 
+static void ssl_console_write(struct console *c, const char *string,
+			      unsigned len)
+{
+	struct line *line = &serial_lines[c->index];
+	if(ssl_init_done)
+		down(&line->sem);
+	console_write_chan(&line->chan_list, string, len);
+	if(ssl_init_done)
+		up(&line->sem);
+}
+
+static struct tty_driver *ssl_console_device(struct console *c, int *index)
+{
+	*index = c->index;
+	return ssl_driver;
+}
+
+static int ssl_console_setup(struct console *co, char *options)
+{
+	return(0);
+}
+
+static struct console ssl_cons = {
+	name:		"ttyS",
+	write:		ssl_console_write,
+	device:		ssl_console_device,
+	setup:		ssl_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
+
 int ssl_init(void)
 {
 	char *new_title;
@@ -227,17 +263,18 @@
 	new_title = add_xterm_umid(opts.xterm_title);
 	if(new_title != NULL) opts.xterm_title = new_title;
 
+	register_console(&ssl_cons);
 	ssl_init_done = 1;
 	return(0);
 }
 
-__initcall(ssl_init);
+late_initcall(ssl_init);
 
 static int ssl_chan_setup(char *str)
 {
-	line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]),
-		   str, 1);
-	return(1);
+	return(line_setup(serial_lines,
+			  sizeof(serial_lines)/sizeof(serial_lines[0]),
+			  str, 1));
 }
 
 __setup("ssl", ssl_chan_setup);
diff -Nru a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
--- a/arch/um/drivers/stdio_console.c	2003-06-11 12:33:07 -07:00
+++ b/arch/um/drivers/stdio_console.c	2004-08-24 02:08:22 -07:00
@@ -83,7 +83,8 @@
 
 static struct line_driver driver = {
 	.name 			= "UML console",
-	.devfs_name 		= "vc/%d",
+	.device_name 		= "tty",
+	.devfs_name 		= "vc/",
 	.major 			= TTY_MAJOR,
 	.minor_start 		= 0,
 	.type 		 	= TTY_DRIVER_TYPE_CONSOLE,
@@ -159,6 +160,15 @@
 
 static int con_init_done = 0;
 
+static struct tty_operations console_ops = {
+	.open 	 		= con_open,
+	.close 	 		= con_close,
+	.write 	 		= con_write,
+	.chars_in_buffer 	= chars_in_buffer,
+	.set_termios 		= set_termios,
+	.write_room		= line_write_room,
+};
+
 int stdio_init(void)
 {
 	char *new_title;
@@ -166,7 +176,8 @@
 	printk(KERN_INFO "Initializing stdio console driver\n");
 
 	console_driver = line_register_devfs(&console_lines, &driver,
-				&console_ops, vts, sizeof(vts)/sizeof(vts[0]));
+					     &console_ops, vts,
+					     sizeof(vts)/sizeof(vts[0]));
 
 	lines_init(vts, sizeof(vts)/sizeof(vts[0]));
 
@@ -178,26 +189,21 @@
 	return(0);
 }
 
-__initcall(stdio_init);
+late_initcall(stdio_init);
 
 static void console_write(struct console *console, const char *string, 
 			  unsigned len)
 {
-	if(con_init_done) down(&vts[console->index].sem);
-	console_write_chan(&vts[console->index].chan_list, string, len);
-	if(con_init_done) up(&vts[console->index].sem);
-}
+	struct line *line = &vts[console->index];
 
-static struct tty_operations console_ops = {
-	.open 	 		= con_open,
-	.close 	 		= con_close,
-	.write 	 		= con_write,
-	.chars_in_buffer 	= chars_in_buffer,
-	.set_termios 		= set_termios,
-	.write_room		= line_write_room,
-};
+	if(con_init_done)
+		down(&line->sem);
+	console_write_chan(&line->chan_list, string, len);
+	if(con_init_done)
+		up(&line->sem);
+}
 
-static struct tty_driver *console_device(struct console *c, int *index)
+static struct tty_driver *um_console_device(struct console *c, int *index)
 {
 	*index = c->index;
 	return console_driver;
@@ -208,22 +214,28 @@
 	return(0);
 }
 
-static struct console stdiocons = INIT_CONSOLE("tty", console_write, 
-					       console_device, console_setup,
-					       CON_PRINTBUFFER);
+static struct console stdiocons = {
+	name:		"tty",
+	write:		console_write,
+	device:		um_console_device,
+	setup:		console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
 
-static void __init stdio_console_init(void)
+static int __init stdio_console_init(void)
 {
 	INIT_LIST_HEAD(&vts[0].chan_list);
 	list_add(&init_console_chan.list, &vts[0].chan_list);
 	register_console(&stdiocons);
+	return(0);
 }
+
 console_initcall(stdio_console_init);
 
 static int console_chan_setup(char *str)
 {
-	line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1);
-	return(1);
+	return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1));
 }
 
 __setup("con", console_chan_setup);
diff -Nru a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
--- a/arch/um/drivers/tty.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/tty.c	2004-08-24 02:08:18 -07:00
@@ -5,7 +5,6 @@
 
 #include <stdio.h>
 #include <termios.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
 #include "chan_user.h"
@@ -30,7 +29,8 @@
 	}
 	str++;
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) 
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL)
 		return(NULL);
 	*data = ((struct tty_chan) { .dev 	= str,
 				     .raw 	= opts->raw });
diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
--- a/arch/um/drivers/ubd_kern.c	2003-09-05 04:31:49 -07:00
+++ b/arch/um/drivers/ubd_kern.c	2004-08-24 02:08:18 -07:00
@@ -8,6 +8,13 @@
  * old style ubd by setting UBD_SHIFT to 0
  * 2002-09-27...2002-10-18 massive tinkering for 2.5
  * partitions have changed in 2.5
+ * 2003-01-29 more tinkering for 2.5.59-1
+ * This should now address the sysfs problems and has
+ * the symlink for devfs to allow for booting with
+ * the common /dev/ubd/discX/... names rather than
+ * only /dev/ubdN/discN this version also has lots of
+ * clean ups preparing for ubd-many.
+ * James McMechan
  */
 
 #define MAJOR_NR UBD_MAJOR
@@ -40,9 +47,12 @@
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "ubd_user.h"
 #include "2_5compat.h"
 #include "os.h"
+#include "mem.h"
+#include "mem_kern.h"
 
 static spinlock_t ubd_io_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED;
@@ -56,6 +66,10 @@
 
 #define MAX_DEV (8)
 
+/* Changed in early boot */
+static int ubd_do_mmap = 0;
+#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
+
 static struct block_device_operations ubd_blops = {
         .owner		= THIS_MODULE,
         .open		= ubd_open,
@@ -67,7 +81,7 @@
 static request_queue_t *ubd_queue;
 
 /* Protected by ubd_lock */
-static int fake_major = 0;
+static int fake_major = MAJOR_NR;
 
 static struct gendisk *ubd_gendisk[MAX_DEV];
 static struct gendisk *fake_gendisk[MAX_DEV];
@@ -96,13 +110,19 @@
 
 struct ubd {
 	char *file;
-	int is_dir;
 	int count;
 	int fd;
 	__u64 size;
 	struct openflags boot_openflags;
 	struct openflags openflags;
+	int no_cow;
 	struct cow cow;
+
+	int map_writes;
+	int map_reads;
+	int nomap_writes;
+	int nomap_reads;
+	int write_maps;
 };
 
 #define DEFAULT_COW { \
@@ -115,21 +135,28 @@
 
 #define DEFAULT_UBD { \
 	.file = 		NULL, \
-	.is_dir =		0, \
 	.count =		0, \
 	.fd =			-1, \
 	.size =			-1, \
 	.boot_openflags =	OPEN_FLAGS, \
 	.openflags =		OPEN_FLAGS, \
+        .no_cow =               0, \
         .cow =			DEFAULT_COW, \
+	.map_writes		= 0, \
+	.map_reads		= 0, \
+	.nomap_writes		= 0, \
+	.nomap_reads		= 0, \
+	.write_maps		= 0, \
 }
 
 struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
 
 static int ubd0_init(void)
 {
-	if(ubd_dev[0].file == NULL)
-		ubd_dev[0].file = "root_fs";
+	struct ubd *dev = &ubd_dev[0];
+
+	if(dev->file == NULL)
+		dev->file = "root_fs";
 	return(0);
 }
 
@@ -196,19 +223,46 @@
 "    Create ide0 entries that map onto ubd devices.\n\n"
 );
 
+static int parse_unit(char **ptr)
+{
+	char *str = *ptr, *end;
+	int n = -1;
+
+	if(isdigit(*str)) {
+		n = simple_strtoul(str, &end, 0);
+		if(end == str)
+			return(-1);
+		*ptr = end;
+	}
+	else if (('a' <= *str) && (*str <= 'h')) {
+		n = *str - 'a';
+		str++;
+		*ptr = str;
+	}
+	return(n);
+}
+
 static int ubd_setup_common(char *str, int *index_out)
 {
+	struct ubd *dev;
 	struct openflags flags = global_openflags;
 	char *backing_file;
 	int n, err;
 
 	if(index_out) *index_out = -1;
-	n = *str++;
+	n = *str;
 	if(n == '='){
-		static int fake_major_allowed = 1;
 		char *end;
 		int major;
 
+		str++;
+		if(!strcmp(str, "mmap")){
+			CHOOSE_MODE(printk("mmap not supported by the ubd "
+					   "driver in tt mode\n"),
+				    ubd_do_mmap = 1);
+			return(0);
+		}
+
 		if(!strcmp(str, "sync")){
 			global_openflags.s = 1;
 			return(0);
@@ -220,20 +274,14 @@
 			return(1);
 		}
 
-		if(!fake_major_allowed){
-			printk(KERN_ERR "Can't assign a fake major twice\n");
-			return(1);
-		}
-
 		err = 1;
  		spin_lock(&ubd_lock);
- 		if(!fake_major_allowed){
+ 		if(fake_major != MAJOR_NR){
  			printk(KERN_ERR "Can't assign a fake major twice\n");
  			goto out1;
  		}
  
  		fake_major = major;
-		fake_major_allowed = 0;
 
 		printk(KERN_INFO "Setting extra ubd major number to %d\n",
 		       major);
@@ -243,25 +291,23 @@
 		return(err);
 	}
 
-	if(n < '0'){
-		printk(KERN_ERR "ubd_setup : index out of range\n"); }
-
-	if((n >= '0') && (n <= '9')) n -= '0';
-	else if((n >= 'a') && (n <= 'z')) n -= 'a';
-	else {
-		printk(KERN_ERR "ubd_setup : device syntax invalid\n");
+	n = parse_unit(&str);
+	if(n < 0){
+		printk(KERN_ERR "ubd_setup : couldn't parse unit number "
+		       "'%s'\n", str);
 		return(1);
 	}
 	if(n >= MAX_DEV){
-		printk(KERN_ERR "ubd_setup : index out of range "
-		       "(%d devices)\n", MAX_DEV);	
+		printk(KERN_ERR "ubd_setup : index %d out of range "
+		       "(%d devices)\n", n, MAX_DEV);
 		return(1);
 	}
 
 	err = 1;
 	spin_lock(&ubd_lock);
 
-	if(ubd_dev[n].file != NULL){
+	dev = &ubd_dev[n];
+	if(dev->file != NULL){
 		printk(KERN_ERR "ubd_setup : device already configured\n");
 		goto out2;
 	}
@@ -276,6 +322,11 @@
 		flags.s = 1;
 		str++;
 	}
+	if (*str == 'd'){
+		dev->no_cow = 1;
+		str++;
+	}
+
 	if(*str++ != '='){
 		printk(KERN_ERR "ubd_setup : Expected '='\n");
 		goto out2;
@@ -284,14 +335,17 @@
 	err = 0;
 	backing_file = strchr(str, ',');
 	if(backing_file){
-		*backing_file = '\0';
-		backing_file++;
+		if(dev->no_cow)
+			printk(KERN_ERR "Can't specify both 'd' and a "
+			       "cow file\n");
+		else {
+			*backing_file = '\0';
+			backing_file++;
+		}
 	}
-	ubd_dev[n].file = str;
-	if(ubd_is_dir(ubd_dev[n].file))
-		ubd_dev[n].is_dir = 1;
-	ubd_dev[n].cow.file = backing_file;
-	ubd_dev[n].boot_openflags = flags;
+	dev->file = str;
+	dev->cow.file = backing_file;
+	dev->boot_openflags = flags;
  out2:
 	spin_unlock(&ubd_lock);
 	return(err);
@@ -321,8 +375,7 @@
 static int fakehd_set = 0;
 static int fakehd(char *str)
 {
-	printk(KERN_INFO 
-	       "fakehd : Changing ubd name to \"hd\".\n");
+	printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
 	fakehd_set = 1;
 	return 1;
 }
@@ -368,32 +421,42 @@
 {
 	struct io_thread_req req;
 	struct request *rq = elv_next_request(ubd_queue);
-	int n;
+	int n, err;
 
 	do_ubd = NULL;
 	intr_count++;
 	n = read_ubd_fs(thread_fd, &req, sizeof(req));
 	if(n != sizeof(req)){
 		printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
-		       "errno = %d\n", os_getpid(), -n);
+		       "err = %d\n", os_getpid(), -n);
 		spin_lock(&ubd_io_lock);
 		end_request(rq, 0);
 		spin_unlock(&ubd_io_lock);
 		return;
 	}
         
-        if((req.offset != ((__u64) (rq->sector)) << 9) ||
-	   (req.length != (rq->current_nr_sectors) << 9))
+	if((req.op != UBD_MMAP) &&
+	   ((req.offset != ((__u64) (rq->sector)) << 9) ||
+	    (req.length != (rq->current_nr_sectors) << 9)))
 		panic("I/O op mismatch");
 	
+	if(req.map_fd != -1){
+		err = physmem_subst_mapping(req.buffer, req.map_fd,
+					    req.map_offset, 1);
+		if(err)
+			printk("ubd_handler - physmem_subst_mapping failed, "
+			       "err = %d\n", -err);
+	}
+
 	ubd_finish(rq, req.error);
 	reactivate_fd(thread_fd, UBD_IRQ);	
 	do_ubd_request(ubd_queue);
 }
 
-static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
+static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
 {
 	ubd_handler();
+	return(IRQ_HANDLED);
 }
 
 /* Only changed by ubd_init, which is an initcall. */
@@ -417,10 +480,14 @@
 
 static void ubd_close(struct ubd *dev)
 {
+	if(ubd_do_mmap)
+		physmem_forget_descriptor(dev->fd);
 	os_close_file(dev->fd);
 	if(dev->cow.file == NULL)
 		return;
 
+	if(ubd_do_mmap)
+		physmem_forget_descriptor(dev->cow.fd);
 	os_close_file(dev->cow.fd);
 	vfree(dev->cow.bitmap);
 	dev->cow.bitmap = NULL;
@@ -429,18 +496,20 @@
 static int ubd_open_dev(struct ubd *dev)
 {
 	struct openflags flags;
-	int err, n, create_cow, *create_ptr;
+	char **back_ptr;
+	int err, create_cow, *create_ptr;
 
+	dev->openflags = dev->boot_openflags;
 	create_cow = 0;
 	create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
-	dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
+	back_ptr = dev->no_cow ? NULL : &dev->cow.file;
+	dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
 				&dev->cow.bitmap_offset, &dev->cow.bitmap_len, 
 				&dev->cow.data_offset, create_ptr);
 
 	if((dev->fd == -ENOENT) && create_cow){
-		n = dev - ubd_dev;
 		dev->fd = create_cow_file(dev->file, dev->cow.file, 
-					  dev->openflags, 1 << 9,
+					  dev->openflags, 1 << 9, PAGE_SIZE,
 					  &dev->cow.bitmap_offset, 
 					  &dev->cow.bitmap_len,
 					  &dev->cow.data_offset);
@@ -455,13 +524,17 @@
 	if(dev->cow.file != NULL){
 		err = -ENOMEM;
 		dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
-		if(dev->cow.bitmap == NULL) goto error;
+		if(dev->cow.bitmap == NULL){
+			printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
+			goto error;
+		}
 		flush_tlb_kernel_vm();
 
 		err = read_cow_bitmap(dev->fd, dev->cow.bitmap, 
 				      dev->cow.bitmap_offset, 
 				      dev->cow.bitmap_len);
-		if(err) goto error;
+		if(err < 0)
+			goto error;
 
 		flags = dev->openflags;
 		flags.w = 0;
@@ -481,17 +554,31 @@
 			
 {
 	struct gendisk *disk;
+	char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")];
+	int err;
 
 	disk = alloc_disk(1 << UBD_SHIFT);
-	if (!disk)
-		return -ENOMEM;
+	if(disk == NULL)
+		return(-ENOMEM);
 
 	disk->major = major;
 	disk->first_minor = unit << UBD_SHIFT;
 	disk->fops = &ubd_blops;
 	set_capacity(disk, size / 512);
-	sprintf(disk->disk_name, "ubd");
-	sprintf(disk->devfs_name, "ubd/disc%d", unit);
+	if(major == MAJOR_NR){
+		sprintf(disk->disk_name, "ubd%c", 'a' + unit);
+		sprintf(disk->devfs_name, "ubd/disc%d", unit);
+		sprintf(from, "ubd/%d", unit);
+		sprintf(to, "disc%d/disc", unit);
+		err = devfs_mk_symlink(from, to);
+		if(err)
+			printk("ubd_new_disk failed to make link from %s to "
+			       "%s, error = %d\n", from, to, err);
+	}
+	else {
+		sprintf(disk->disk_name, "ubd_fake%d", unit);
+		sprintf(disk->devfs_name, "ubd_fake/disc%d", unit);
+	}
 
 	disk->private_data = &ubd_dev[unit];
 	disk->queue = ubd_queue;
@@ -506,24 +593,21 @@
 	struct ubd *dev = &ubd_dev[n];
 	int err;
 
-	if(dev->is_dir)
-		return(-EISDIR);
-
-	if (!dev->file)
+	if(dev->file == NULL)
 		return(-ENODEV);
 
 	if (ubd_open_dev(dev))
 		return(-ENODEV);
 
 	err = ubd_file_size(dev, &dev->size);
-	if(err)
+	if(err < 0)
 		return(err);
 
 	err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
 	if(err) 
 		return(err);
  
-	if(fake_major)
+	if(fake_major != MAJOR_NR)
 		ubd_new_disk(fake_major, dev->size, n, 
 			     &fake_gendisk[n]);
 
@@ -561,42 +645,42 @@
 	return(err);
 }
 
-static int ubd_get_config(char *dev, char *str, int size, char **error_out)
+static int ubd_get_config(char *name, char *str, int size, char **error_out)
 {
-	struct ubd *ubd;
+	struct ubd *dev;
 	char *end;
-	int major, n = 0;
+	int n, len = 0;
 
-	major = simple_strtoul(dev, &end, 0);
-	if((*end != '\0') || (end == dev)){
-		*error_out = "ubd_get_config : didn't parse major number";
+	n = simple_strtoul(name, &end, 0);
+	if((*end != '\0') || (end == name)){
+		*error_out = "ubd_get_config : didn't parse device number";
 		return(-1);
 	}
 
-	if((major >= MAX_DEV) || (major < 0)){
-		*error_out = "ubd_get_config : major number out of range";
+	if((n >= MAX_DEV) || (n < 0)){
+		*error_out = "ubd_get_config : device number out of range";
 		return(-1);
 	}
 
-	ubd = &ubd_dev[major];
+	dev = &ubd_dev[n];
 	spin_lock(&ubd_lock);
 
-	if(ubd->file == NULL){
-		CONFIG_CHUNK(str, size, n, "", 1);
+	if(dev->file == NULL){
+		CONFIG_CHUNK(str, size, len, "", 1);
 		goto out;
 	}
 
-	CONFIG_CHUNK(str, size, n, ubd->file, 0);
+	CONFIG_CHUNK(str, size, len, dev->file, 0);
 
-	if(ubd->cow.file != NULL){
-		CONFIG_CHUNK(str, size, n, ",", 0);
-		CONFIG_CHUNK(str, size, n, ubd->cow.file, 1);
+	if(dev->cow.file != NULL){
+		CONFIG_CHUNK(str, size, len, ",", 0);
+		CONFIG_CHUNK(str, size, len, dev->cow.file, 1);
 	}
-	else CONFIG_CHUNK(str, size, n, "", 1);
+	else CONFIG_CHUNK(str, size, len, "", 1);
 
  out:
 	spin_unlock(&ubd_lock);
-	return(n);
+	return(len);
 }
 
 static int ubd_remove(char *str)
@@ -604,11 +688,9 @@
 	struct ubd *dev;
 	int n, err = -ENODEV;
 
-	if(!isdigit(*str))
-		return(err);	/* it should be a number 0-7/a-h */
+	n = parse_unit(&str);
 
-	n = *str - '0';
-	if(n >= MAX_DEV) 
+	if((n < 0) || (n >= MAX_DEV))
 		return(err);
 
 	dev = &ubd_dev[n];
@@ -669,7 +751,7 @@
 		
 	elevator_init(ubd_queue, &elevator_noop);
 
-	if (fake_major != 0) {
+	if (fake_major != MAJOR_NR) {
 		char name[sizeof("ubd_nnn\0")];
 
 		snprintf(name, sizeof(name), "ubd_%d", fake_major);
@@ -696,6 +778,7 @@
 	io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), 
 				 &thread_fd);
 	if(io_pid < 0){
+		io_pid = -1;
 		printk(KERN_ERR 
 		       "ubd : Failed to start I/O thread (errno = %d) - "
 		       "falling back to synchronous I/O\n", -io_pid);
@@ -703,8 +786,8 @@
 	}
 	err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, 
 			     SA_INTERRUPT, "ubd", ubd_dev);
-	if(err != 0) printk(KERN_ERR 
-			    "um_request_irq failed - errno = %d\n", -err);
+	if(err != 0)
+		printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
 	return(err);
 }
 
@@ -714,15 +797,9 @@
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ubd *dev = disk->private_data;
-	int err = -EISDIR;
+	int err = 0;
 
-	if(dev->is_dir == 1)
-		goto out;
-
-	err = 0;
 	if(dev->count == 0){
-		dev->openflags = dev->boot_openflags;
-
 		err = ubd_open_dev(dev);
 		if(err){
 			printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
@@ -749,62 +826,156 @@
 	return(0);
 }
 
-void cowify_req(struct io_thread_req *req, struct ubd *dev)
+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
+			  __u64 *cow_offset, unsigned long *bitmap,
+			  __u64 bitmap_offset, unsigned long *bitmap_words,
+			  __u64 bitmap_len)
+{
+	__u64 sector = io_offset >> 9;
+	int i, update_bitmap = 0;
+
+	for(i = 0; i < length >> 9; i++){
+		if(cow_mask != NULL)
+			ubd_set_bit(i, (unsigned char *) cow_mask);
+		if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
+			continue;
+
+		update_bitmap = 1;
+		ubd_set_bit(sector + i, (unsigned char *) bitmap);
+	}
+
+	if(!update_bitmap)
+		return;
+
+	*cow_offset = sector / (sizeof(unsigned long) * 8);
+
+	/* This takes care of the case where we're exactly at the end of the
+	 * device, and *cow_offset + 1 is off the end.  So, just back it up
+	 * by one word.  Thanks to Lynn Kerby for the fix and James McMechan
+	 * for the original diagnosis.
+	 */
+	if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
+			   sizeof(unsigned long) - 1))
+		(*cow_offset)--;
+
+	bitmap_words[0] = bitmap[*cow_offset];
+	bitmap_words[1] = bitmap[*cow_offset + 1];
+
+	*cow_offset *= sizeof(unsigned long);
+	*cow_offset += bitmap_offset;
+}
+
+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
+		       __u64 bitmap_offset, __u64 bitmap_len)
 {
-        int i, update_bitmap, sector = req->offset >> 9;
+	__u64 sector = req->offset >> 9;
+	int i;
 
 	if(req->length > (sizeof(req->sector_mask) * 8) << 9)
 		panic("Operation too long");
+
 	if(req->op == UBD_READ) {
 		for(i = 0; i < req->length >> 9; i++){
-			if(ubd_test_bit(sector + i, (unsigned char *) 
-					dev->cow.bitmap)){
+			if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
 				ubd_set_bit(i, (unsigned char *) 
 					    &req->sector_mask);
-			}
                 }
-        } 
-        else {
-		update_bitmap = 0;
-		for(i = 0; i < req->length >> 9; i++){
-			ubd_set_bit(i, (unsigned char *) 
-				    &req->sector_mask);
-			if(!ubd_test_bit(sector + i, (unsigned char *) 
-					 dev->cow.bitmap))
-				update_bitmap = 1;
-			ubd_set_bit(sector + i, (unsigned char *) 
-				    dev->cow.bitmap);
-		}
-		if(update_bitmap){
-			req->cow_offset = sector / (sizeof(unsigned long) * 8);
-			req->bitmap_words[0] = 
-				dev->cow.bitmap[req->cow_offset];
-			req->bitmap_words[1] = 
-				dev->cow.bitmap[req->cow_offset + 1];
-			req->cow_offset *= sizeof(unsigned long);
-			req->cow_offset += dev->cow.bitmap_offset;
+	}
+	else cowify_bitmap(req->offset, req->length, &req->sector_mask,
+			   &req->cow_offset, bitmap, bitmap_offset,
+			   req->bitmap_words, bitmap_len);
+}
+
+static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
+{
+	__u64 sector;
+	unsigned char *bitmap;
+	int bit, i;
+
+	/* mmap must have been requested on the command line */
+	if(!ubd_do_mmap)
+		return(-1);
+
+	/* The buffer must be page aligned */
+	if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
+		return(-1);
+
+	/* The request must be a page long */
+	if((req->current_nr_sectors << 9) != PAGE_SIZE)
+		return(-1);
+
+	if(dev->cow.file == NULL)
+		return(dev->fd);
+
+	sector = offset >> 9;
+	bitmap = (unsigned char *) dev->cow.bitmap;
+	bit = ubd_test_bit(sector, bitmap);
+
+	for(i = 1; i < req->current_nr_sectors; i++){
+		if(ubd_test_bit(sector + i, bitmap) != bit)
+			return(-1);
+	}
+
+	if(bit || (rq_data_dir(req) == WRITE))
+		offset += dev->cow.data_offset;
+
+	/* The data on disk must be page aligned */
+	if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
+		return(-1);
+
+	return(bit ? dev->fd : dev->cow.fd);
+}
+
+static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
+				struct request *req,
+				struct io_thread_req *io_req)
+{
+	int err;
+
+	if(rq_data_dir(req) == WRITE){
+		/* Writes are almost no-ops since the new data is already in the
+		 * host page cache
+		 */
+		dev->map_writes++;
+		if(dev->cow.file != NULL)
+			cowify_bitmap(io_req->offset, io_req->length,
+				      &io_req->sector_mask, &io_req->cow_offset,
+				      dev->cow.bitmap, dev->cow.bitmap_offset,
+				      io_req->bitmap_words,
+				      dev->cow.bitmap_len);
+	}
+	else {
+		int w;
+
+		if((dev->cow.file != NULL) && (fd == dev->cow.fd))
+			w = 0;
+		else w = dev->openflags.w;
+
+		if((dev->cow.file != NULL) && (fd == dev->fd))
+			offset += dev->cow.data_offset;
+
+		err = physmem_subst_mapping(req->buffer, fd, offset, w);
+		if(err){
+			printk("physmem_subst_mapping failed, err = %d\n",
+			       -err);
+			return(1);
 		}
+		dev->map_reads++;
 	}
+	io_req->op = UBD_MMAP;
+	io_req->buffer = req->buffer;
+	return(0);
 }
 
 static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
 	struct gendisk *disk = req->rq_disk;
 	struct ubd *dev = disk->private_data;
-	__u64 block;
-	int nsect;
+	__u64 offset;
+	int len, fd;
 
 	if(req->rq_status == RQ_INACTIVE) return(1);
 
-	if(dev->is_dir){
-		strcpy(req->buffer, "HOSTFS:");
-		strcat(req->buffer, dev->file);
- 		spin_lock(&ubd_io_lock);
-		end_request(req, 1);
- 		spin_unlock(&ubd_io_lock);
-		return(1);
-	}
-
 	if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
 		printk("Write attempted on readonly ubd device %s\n", 
 		       disk->disk_name);
@@ -814,23 +985,49 @@
 		return(1);
 	}
 
-        block = req->sector;
-        nsect = req->current_nr_sectors;
+	offset = ((__u64) req->sector) << 9;
+	len = req->current_nr_sectors << 9;
 
-	io_req->op = rq_data_dir(req) == READ ? UBD_READ : UBD_WRITE;
 	io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
 	io_req->fds[1] = dev->fd;
+	io_req->map_fd = -1;
+	io_req->cow_offset = -1;
+	io_req->offset = offset;
+	io_req->length = len;
+	io_req->error = 0;
+	io_req->sector_mask = 0;
+
+	fd = mmap_fd(req, dev, io_req->offset);
+	if(fd > 0){
+		/* If mmapping is otherwise OK, but the first access to the
+		 * page is a write, then it's not mapped in yet.  So we have
+		 * to write the data to disk first, then we can map the disk
+		 * page in and continue normally from there.
+		 */
+		if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
+			io_req->map_fd = dev->fd;
+			io_req->map_offset = io_req->offset +
+				dev->cow.data_offset;
+			dev->write_maps++;
+		}
+		else return(prepare_mmap_request(dev, fd, io_req->offset, req,
+						 io_req));
+	}
+
+	if(rq_data_dir(req) == READ)
+		dev->nomap_reads++;
+	else dev->nomap_writes++;
+
+	io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
 	io_req->offsets[0] = 0;
 	io_req->offsets[1] = dev->cow.data_offset;
-	io_req->offset = ((__u64) block) << 9;
-	io_req->length = nsect << 9;
 	io_req->buffer = req->buffer;
 	io_req->sectorsize = 1 << 9;
-	io_req->sector_mask = 0;
-	io_req->cow_offset = -1;
-	io_req->error = 0;
 
-        if(dev->cow.file != NULL) cowify_req(io_req, dev);
+	if(dev->cow.file != NULL)
+		cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
+			   dev->cow.bitmap_len);
+
 	return(0);
 }
 
@@ -841,7 +1038,7 @@
 	int err, n;
 
 	if(thread_fd == -1){
-		while(!list_empty(&q->queue_head)){
+		while(!elv_queue_empty(q)){
 			req = elv_next_request(q);
 			err = prepare_request(req, &io_req);
 			if(!err){
@@ -851,7 +1048,8 @@
 		}
 	}
 	else {
-		if(do_ubd || list_empty(&q->queue_head)) return;
+		if(do_ubd || elv_queue_empty(q))
+			return;
 		req = elv_next_request(q);
 		err = prepare_request(req, &io_req);
 		if(!err){
@@ -885,7 +1083,7 @@
 		g.heads = 128;
 		g.sectors = 32;
 		g.cylinders = dev->size / (128 * 32 * 512);
-		g.start = 2;
+		g.start = get_start_sect(inode->i_bdev);
 		return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
 
 	case HDIO_SET_UNMASKINTR:
@@ -934,6 +1132,142 @@
 	}
 	return(-EINVAL);
 }
+
+static int ubd_check_remapped(int fd, unsigned long address, int is_write,
+			      __u64 offset)
+{
+	__u64 bitmap_offset;
+	unsigned long new_bitmap[2];
+	int i, err, n;
+
+	/* If it's not a write access, we can't do anything about it */
+	if(!is_write)
+		return(0);
+
+	/* We have a write */
+	for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
+		struct ubd *dev = &ubd_dev[i];
+
+		if((dev->fd != fd) && (dev->cow.fd != fd))
+			continue;
+
+		/* It's a write to a ubd device */
+
+		if(!dev->openflags.w){
+			/* It's a write access on a read-only device - probably
+			 * shouldn't happen.  If the kernel is trying to change
+			 * something with no intention of writing it back out,
+			 * then this message will clue us in that this needs
+			 * fixing
+			 */
+			printk("Write access to mapped page from readonly ubd "
+			       "device %d\n", i);
+			return(0);
+		}
+
+		/* It's a write to a writeable ubd device - it must be COWed
+		 * because, otherwise, the page would have been mapped in
+		 * writeable
+		 */
+
+		if(!dev->cow.file)
+			panic("Write fault on writeable non-COW ubd device %d",
+			      i);
+
+		/* It should also be an access to the backing file since the
+		 * COW pages should be mapped in read-write
+		 */
+
+		if(fd == dev->fd)
+			panic("Write fault on a backing page of ubd "
+			      "device %d\n", i);
+
+		/* So, we do the write, copying the backing data to the COW
+		 * file...
+		 */
+
+		err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
+		if(err < 0)
+			panic("Couldn't seek to %lld in COW file of ubd "
+			      "device %d, err = %d",
+			      offset + dev->cow.data_offset, i, -err);
+
+		n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
+		if(n != PAGE_SIZE)
+			panic("Couldn't copy data to COW file of ubd "
+			      "device %d, err = %d", i, -n);
+
+		/* ... updating the COW bitmap... */
+
+		cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
+			      dev->cow.bitmap, dev->cow.bitmap_offset,
+			      new_bitmap, dev->cow.bitmap_len);
+
+		err = os_seek_file(dev->fd, bitmap_offset);
+		if(err < 0)
+			panic("Couldn't seek to %lld in COW file of ubd "
+			      "device %d, err = %d", bitmap_offset, i, -err);
+
+		n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
+		if(n != sizeof(new_bitmap))
+			panic("Couldn't update bitmap  of ubd device %d, "
+			      "err = %d", i, -n);
+
+		/* Maybe we can map the COW page in, and maybe we can't.  If
+		 * it is a pre-V3 COW file, we can't, since the alignment will
+		 * be wrong.  If it is a V3 or later COW file which has been
+		 * moved to a system with a larger page size, then maybe we
+		 * can't, depending on the exact location of the page.
+		 */
+
+		offset += dev->cow.data_offset;
+
+		/* Remove the remapping, putting the original anonymous page
+		 * back.  If the COW file can be mapped in, that is done.
+		 * Otherwise, the COW page is read in.
+		 */
+
+		if(!physmem_remove_mapping((void *) address))
+			panic("Address 0x%lx not remapped by ubd device %d",
+			      address, i);
+		if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
+			physmem_subst_mapping((void *) address, dev->fd,
+					      offset, 1);
+		else {
+			err = os_seek_file(dev->fd, offset);
+			if(err < 0)
+				panic("Couldn't seek to %lld in COW file of "
+				      "ubd device %d, err = %d", offset, i,
+				      -err);
+
+			n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
+			if(n != PAGE_SIZE)
+				panic("Failed to read page from offset %llx of "
+				      "COW file of ubd device %d, err = %d",
+				      offset, i, -n);
+		}
+
+		return(1);
+	}
+
+	/* It's not a write on a ubd device */
+	return(0);
+}
+
+static struct remapper ubd_remapper = {
+	.list	= LIST_HEAD_INIT(ubd_remapper.list),
+	.proc	= ubd_check_remapped,
+};
+
+static int ubd_remapper_setup(void)
+{
+	if(ubd_do_mmap)
+		register_remapper(&ubd_remapper);
+
+	return(0);
+}
+
+__initcall(ubd_remapper_setup);
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -Nru a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
--- a/arch/um/drivers/ubd_user.c	2002-12-26 18:09:18 -08:00
+++ b/arch/um/drivers/ubd_user.c	2004-08-24 02:08:18 -07:00
@@ -11,11 +11,8 @@
 #include <signal.h>
 #include <string.h>
 #include <netinet/in.h>
-#include <sys/stat.h>
 #include <sys/time.h>
-#include <sys/fcntl.h>
 #include <sys/socket.h>
-#include <string.h>
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "asm/types.h"
@@ -24,146 +21,30 @@
 #include "user.h"
 #include "ubd_user.h"
 #include "os.h"
+#include "cow.h"
 
 #include <endian.h>
 #include <byteswap.h>
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define ntohll(x) (x)
-# define htonll(x) (x)
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-# define ntohll(x)  bswap_64(x)
-# define htonll(x)  bswap_64(x)
-#else
-#error "__BYTE_ORDER not defined"
-#endif
-
-#define PATH_LEN_V1 256
-
-struct cow_header_v1 {
-	int magic;
-	int version;
-	char backing_file[PATH_LEN_V1];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
-
-#define PATH_LEN_V2 MAXPATHLEN
-
-struct cow_header_v2 {
-	unsigned long magic;
-	unsigned long version;
-	char backing_file[PATH_LEN_V2];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
-
-union cow_header {
-	struct cow_header_v1 v1;
-	struct cow_header_v2 v2;
-};
-
-#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
-#define COW_VERSION 2
-
-static void sizes(__u64 size, int sectorsize, int bitmap_offset, 
-		  unsigned long *bitmap_len_out, int *data_offset_out)
-{
-	*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
-
-	*data_offset_out = bitmap_offset + *bitmap_len_out;
-	*data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
-	*data_offset_out *= sectorsize;
-}
-
-static int read_cow_header(int fd, int *magic_out, char **backing_file_out, 
-			   time_t *mtime_out, __u64 *size_out, 
-			   int *sectorsize_out, int *bitmap_offset_out)
-{
-	union cow_header *header;
-	char *file;
-	int err, n;
-	unsigned long version, magic;
-
-	header = um_kmalloc(sizeof(*header));
-	if(header == NULL){
-		printk("read_cow_header - Failed to allocate header\n");
-		return(-ENOMEM);
-	}
-	err = -EINVAL;
-	n = read(fd, header, sizeof(*header));
-	if(n < offsetof(typeof(header->v1), backing_file)){
-		printk("read_cow_header - short header\n");
-		goto out;
-	}
-
-	magic = header->v1.magic;
-	if(magic == COW_MAGIC) {
-		version = header->v1.version;
-	}
-	else if(magic == ntohl(COW_MAGIC)){
-		version = ntohl(header->v1.version);
-	}
-	else goto out;
-
-	*magic_out = COW_MAGIC;
-
-	if(version == 1){
-		if(n < sizeof(header->v1)){
-			printk("read_cow_header - failed to read V1 header\n");
-			goto out;
-		}
-		*mtime_out = header->v1.mtime;
-		*size_out = header->v1.size;
-		*sectorsize_out = header->v1.sectorsize;
-		*bitmap_offset_out = sizeof(header->v1);
-		file = header->v1.backing_file;
-	}
-	else if(version == 2){
-		if(n < sizeof(header->v2)){
-			printk("read_cow_header - failed to read V2 header\n");
-			goto out;
-		}
-		*mtime_out = ntohl(header->v2.mtime);
-		*size_out = ntohll(header->v2.size);
-		*sectorsize_out = ntohl(header->v2.sectorsize);
-		*bitmap_offset_out = sizeof(header->v2);
-		file = header->v2.backing_file;
-	}
-	else {
-		printk("read_cow_header - invalid COW version\n");
-		goto out;
-	}
-	err = -ENOMEM;
-	*backing_file_out = uml_strdup(file);
-	if(*backing_file_out == NULL){
-		printk("read_cow_header - failed to allocate backing file\n");
-		goto out;
-	}
-	err = 0;
- out:
-	kfree(header);
-	return(err);
-}
 
 static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
 {
-	struct stat buf1, buf2;
+	struct uml_stat buf1, buf2;
+	int err;
 
 	if(from_cmdline == NULL) return(1);
 	if(!strcmp(from_cmdline, from_cow)) return(1);
 
-	if(stat(from_cmdline, &buf1) < 0){
-		printk("Couldn't stat '%s', errno = %d\n", from_cmdline, 
-		       errno);
+	err = os_stat_file(from_cmdline, &buf1);
+	if(err < 0){
+		printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
 		return(1);
 	}
-	if(stat(from_cow, &buf2) < 0){
-		printk("Couldn't stat '%s', errno = %d\n", from_cow, errno);
+	err = os_stat_file(from_cow, &buf2);
+	if(err < 0){
+		printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
 		return(1);
 	}
-	if((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino))
+	if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
 		return(1);
 
 	printk("Backing file mismatch - \"%s\" requested,\n"
@@ -174,20 +55,21 @@
 
 static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
 {
-	struct stat64 buf;
+	unsigned long modtime;
 	long long actual;
 	int err;
 
-  	if(stat64(file, &buf) < 0){
-		printk("Failed to stat backing file \"%s\", errno = %d\n",
-		       file, errno);
-		return(-errno);
+	err = os_file_modtime(file, &modtime);
+	if(err < 0){
+		printk("Failed to get modification time of backing file "
+		       "\"%s\", err = %d\n", file, -err);
+		return(err);
 	}
 
 	err = os_file_size(file, &actual);
-	if(err){
+	if(err < 0){
 		printk("Failed to get size of backing file \"%s\", "
-		       "errno = %d\n", file, -err);
+		       "err = %d\n", file, -err);
 		return(err);
 	}
 
@@ -196,9 +78,9 @@
 		       "file\n", size, actual);
 		return(-EINVAL);
 	}
-	if(buf.st_mtime != mtime){
+	if(modtime != mtime){
 		printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
-		       "file\n", mtime, buf.st_mtime);
+		       "file\n", mtime, modtime);
 		return(-EINVAL);
 	}
 	return(0);
@@ -209,124 +91,16 @@
 	int err;
 
 	err = os_seek_file(fd, offset);
-	if(err != 0) return(-errno);
-	err = read(fd, buf, len);
-	if(err < 0) return(-errno);
-	return(0);
-}
+	if(err < 0)
+		return(err);
 
-static int absolutize(char *to, int size, char *from)
-{
-	char save_cwd[256], *slash;
-	int remaining;
+	err = os_read_file(fd, buf, len);
+	if(err < 0)
+		return(err);
 
-	if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
-		printk("absolutize : unable to get cwd - errno = %d\n", errno);
-		return(-1);
-	}
-	slash = strrchr(from, '/');
-	if(slash != NULL){
-		*slash = '\0';
-		if(chdir(from)){
-			*slash = '/';
-			printk("absolutize : Can't cd to '%s' - errno = %d\n",
-			       from, errno);
-			return(-1);
-		}
-		*slash = '/';
-		if(getcwd(to, size) == NULL){
-			printk("absolutize : unable to get cwd of '%s' - "
-			       "errno = %d\n", from, errno);
-			return(-1);
-		}
-		remaining = size - strlen(to);
-		if(strlen(slash) + 1 > remaining){
-			printk("absolutize : unable to fit '%s' into %d "
-			       "chars\n", from, size);
-			return(-1);
-		}
-		strcat(to, slash);
-	}
-	else {
-		if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
-			printk("absolutize : unable to fit '%s' into %d "
-			       "chars\n", from, size);
-			return(-1);
-		}
-		strcpy(to, save_cwd);
-		strcat(to, "/");
-		strcat(to, from);
-	}
-	chdir(save_cwd);
 	return(0);
 }
 
-static int write_cow_header(char *cow_file, int fd, char *backing_file, 
-			    int sectorsize, long long *size)
-{
-        struct cow_header_v2 *header;
-	struct stat64 buf;
-	int err;
-
-	err = os_seek_file(fd, 0);
-	if(err != 0){
-		printk("write_cow_header - lseek failed, errno = %d\n", errno);
-		return(-errno);
-	}
-
-	err = -ENOMEM;
-	header = um_kmalloc(sizeof(*header));
-	if(header == NULL){
-		printk("Failed to allocate COW V2 header\n");
-		goto out;
-	}
-	header->magic = htonl(COW_MAGIC);
-	header->version = htonl(COW_VERSION);
-
-	err = -EINVAL;
-	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
-		printk("Backing file name \"%s\" is too long - names are "
-		       "limited to %d characters\n", backing_file, 
-		       sizeof(header->backing_file) - 1);
-		goto out_free;
-	}
-
-	if(absolutize(header->backing_file, sizeof(header->backing_file), 
-		      backing_file))
-		goto out_free;
-
-	err = stat64(header->backing_file, &buf);
-	if(err < 0){
-		printk("Stat of backing file '%s' failed, errno = %d\n",
-		       header->backing_file, errno);
-		err = -errno;
-		goto out_free;
-	}
-
-	err = os_file_size(header->backing_file, size);
-	if(err){
-		printk("Couldn't get size of backing file '%s', errno = %d\n",
-		       header->backing_file, -*size);
-		goto out_free;
-	}
-
-	header->mtime = htonl(buf.st_mtime);
-	header->size = htonll(*size);
-	header->sectorsize = htonl(sectorsize);
-
-	err = write(fd, header, sizeof(*header));
-	if(err != sizeof(*header)){
-		printk("Write of header to new COW file '%s' failed, "
-		       "errno = %d\n", cow_file, errno);
-		goto out_free;
-	}
-	err = 0;
- out_free:
-	kfree(header);
- out:
-	return(err);
-}
-
 int open_ubd_file(char *file, struct openflags *openflags, 
 		  char **backing_file_out, int *bitmap_offset_out, 
 		  unsigned long *bitmap_len_out, int *data_offset_out, 
@@ -334,26 +108,36 @@
 {
 	time_t mtime;
 	__u64 size;
+	__u32 version, align;
 	char *backing_file;
-        int fd, err, sectorsize, magic, same, mode = 0644;
+	int fd, err, sectorsize, same, mode = 0644;
 
-        if((fd = os_open_file(file, *openflags, mode)) < 0){
+	fd = os_open_file(file, *openflags, mode);
+	if(fd < 0){
 		if((fd == -ENOENT) && (create_cow_out != NULL))
 			*create_cow_out = 1;
                 if(!openflags->w ||
                    ((errno != EROFS) && (errno != EACCES))) return(-errno);
 		openflags->w = 0;
-                if((fd = os_open_file(file, *openflags, mode)) < 0) 
+		fd = os_open_file(file, *openflags, mode);
+		if(fd < 0)
 			return(fd);
         }
+
+	err = os_lock_file(fd, openflags->w);
+	if(err < 0){
+		printk("Failed to lock '%s', err = %d\n", file, -err);
+		goto out_close;
+	}
+
 	if(backing_file_out == NULL) return(fd);
 
-	err = read_cow_header(fd, &magic, &backing_file, &mtime, &size, 
-			      &sectorsize, bitmap_offset_out);
+	err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
+			      &size, &sectorsize, &align, bitmap_offset_out);
 	if(err && (*backing_file_out != NULL)){
 		printk("Failed to read COW header from COW file \"%s\", "
-		       "errno = %d\n", file, err);
-		goto error;
+		       "errno = %d\n", file, -err);
+		goto out_close;
 	}
 	if(err) return(fd);
 
@@ -363,36 +147,33 @@
 
 	if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
 		printk("Switching backing file to '%s'\n", *backing_file_out);
-		err = write_cow_header(file, fd, *backing_file_out, 
-				       sectorsize, &size);
+		err = write_cow_header(file, fd, *backing_file_out,
+				       sectorsize, align, &size);
 		if(err){
-			printk("Switch failed, errno = %d\n", err);
+			printk("Switch failed, errno = %d\n", -err);
 			return(err);
 		}
 	}
 	else {
 		*backing_file_out = backing_file;
 		err = backing_file_mismatch(*backing_file_out, size, mtime);
-		if(err) goto error;
+		if(err) goto out_close;
 	}
 
-	sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, 
-	      data_offset_out);
+	cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
+		  bitmap_len_out, data_offset_out);
 
         return(fd);
- error:
-	close(fd);
+ out_close:
+	os_close_file(fd);
 	return(err);
 }
 
 int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
-		    int sectorsize, int *bitmap_offset_out, 
+		    int sectorsize, int alignment, int *bitmap_offset_out,
 		    unsigned long *bitmap_len_out, int *data_offset_out)
 {
-	__u64 blocks;
-	long zero;
-	int err, fd, i;
-	long long size;
+	int err, fd;
 
 	flags.c = 1;
 	fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
@@ -403,57 +184,49 @@
 		goto out;
 	}
 
-	err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
-	if(err) goto out_close;
-
-	blocks = (size + sectorsize - 1) / sectorsize;
-	blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8);
-	zero = 0;
-	for(i = 0; i < blocks; i++){
-		err = write(fd, &zero, sizeof(zero));
-		if(err != sizeof(zero)){
-			printk("Write of bitmap to new COW file '%s' failed, "
-			       "errno = %d\n", cow_file, errno);
-			goto out_close;
-		}
-	}
-
-	sizes(size, sectorsize, sizeof(struct cow_header_v2), 
-	      bitmap_len_out, data_offset_out);
-	*bitmap_offset_out = sizeof(struct cow_header_v2);
-
-	return(fd);
-
- out_close:
-	close(fd);
+	err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
+			    bitmap_offset_out, bitmap_len_out,
+			    data_offset_out);
+	if(!err)
+		return(fd);
+	os_close_file(fd);
  out:
 	return(err);
 }
 
+/* XXX Just trivial wrappers around os_read_file and os_write_file */
 int read_ubd_fs(int fd, void *buffer, int len)
 {
-	int n;
-
-	n = read(fd, buffer, len);
-	if(n < 0) return(-errno);
-	else return(n);
+	return(os_read_file(fd, buffer, len));
 }
 
 int write_ubd_fs(int fd, char *buffer, int len)
 {
-	int n;
-
-	n = write(fd, buffer, len);
-	if(n < 0) return(-errno);
-	else return(n);
+	return(os_write_file(fd, buffer, len));
 }
 
-int ubd_is_dir(char *file)
+static int update_bitmap(struct io_thread_req *req)
 {
-	struct stat64 buf;
+	int n;
+
+	if(req->cow_offset == -1)
+		return(0);
+
+	n = os_seek_file(req->fds[1], req->cow_offset);
+	if(n < 0){
+		printk("do_io - bitmap lseek failed : err = %d\n", -n);
+		return(1);
+	}
+
+	n = os_write_file(req->fds[1], &req->bitmap_words,
+		          sizeof(req->bitmap_words));
+	if(n != sizeof(req->bitmap_words)){
+		printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
+		       req->fds[1]);
+		return(1);
+	}
 
-	if(stat64(file, &buf) < 0) return(0);
-	return(S_ISDIR(buf.st_mode));
+	return(0);
 }
 
 void do_io(struct io_thread_req *req)
@@ -461,8 +234,18 @@
 	char *buf;
 	unsigned long len;
 	int n, nsectors, start, end, bit;
+	int err;
 	__u64 off;
 
+	if(req->op == UBD_MMAP){
+		/* Touch the page to force the host to do any necessary IO to
+		 * get it into memory
+		 */
+		n = *((volatile int *) req->buffer);
+		req->error = update_bitmap(req);
+		return;
+	}
+
 	nsectors = req->length / req->sectorsize;
 	start = 0;
 	do {
@@ -473,15 +256,14 @@
 				    &req->sector_mask) == bit))
 			end++;
 
-		if(end != nsectors)
-			printk("end != nsectors\n");
 		off = req->offset + req->offsets[bit] + 
 			start * req->sectorsize;
 		len = (end - start) * req->sectorsize;
 		buf = &req->buffer[start * req->sectorsize];
 
-		if(os_seek_file(req->fds[bit], off) != 0){
-			printk("do_io - lseek failed : errno = %d\n", errno);
+		err = os_seek_file(req->fds[bit], off);
+		if(err < 0){
+			printk("do_io - lseek failed : err = %d\n", -err);
 			req->error = 1;
 			return;
 		}
@@ -490,11 +272,10 @@
 			do {
 				buf = &buf[n];
 				len -= n;
-				n = read(req->fds[bit], buf, len);
+				n = os_read_file(req->fds[bit], buf, len);
 				if (n < 0) {
-					printk("do_io - read returned %d : "
-					       "errno = %d fd = %d\n", n,
-					       errno, req->fds[bit]);
+					printk("do_io - read failed, err = %d "
+					       "fd = %d\n", -n, req->fds[bit]);
 					req->error = 1;
 					return;
 				}
@@ -502,11 +283,10 @@
 			if (n < len) memset(&buf[n], 0, len - n);
 		}
 		else {
-			n = write(req->fds[bit], buf, len);
+			n = os_write_file(req->fds[bit], buf, len);
 			if(n != len){
-				printk("do_io - write returned %d : "
-				       "errno = %d fd = %d\n", n, 
-				       errno, req->fds[bit]);
+				printk("do_io - write failed err = %d "
+				       "fd = %d\n", -n, req->fds[bit]);
 				req->error = 1;
 				return;
 			}
@@ -515,24 +295,7 @@
 		start = end;
 	} while(start < nsectors);
 
-	if(req->cow_offset != -1){
-		if(os_seek_file(req->fds[1], req->cow_offset) != 0){
-			printk("do_io - bitmap lseek failed : errno = %d\n",
-			       errno);
-			req->error = 1;
-			return;
-		}
-		n = write(req->fds[1], &req->bitmap_words, 
-			  sizeof(req->bitmap_words));
-		if(n != sizeof(req->bitmap_words)){
-			printk("do_io - bitmap update returned %d : "
-			       "errno = %d fd = %d\n", n, errno, req->fds[1]);
-			req->error = 1;
-			return;
-		}
-	}
-	req->error = 0;
-	return;
+	req->error = update_bitmap(req);
 }
 
 /* Changed in start_io_thread, which is serialized by being called only
@@ -550,19 +313,23 @@
 
 	signal(SIGWINCH, SIG_IGN);
 	while(1){
-		n = read(kernel_fd, &req, sizeof(req));
-		if(n < 0) printk("io_thread - read returned %d, errno = %d\n",
-				 n, errno);
-		else if(n < sizeof(req)){
-			printk("io_thread - short read : length = %d\n", n);
+		n = os_read_file(kernel_fd, &req, sizeof(req));
+		if(n != sizeof(req)){
+			if(n < 0)
+				printk("io_thread - read failed, fd = %d, "
+				       "err = %d\n", kernel_fd, -n);
+			else {
+				printk("io_thread - short read, fd = %d, "
+				       "length = %d\n", kernel_fd, n);
+			}
 			continue;
 		}
 		io_count++;
 		do_io(&req);
-		n = write(kernel_fd, &req, sizeof(req));
+		n = os_write_file(kernel_fd, &req, sizeof(req));
 		if(n != sizeof(req))
-			printk("io_thread - write failed, errno = %d\n",
-			       errno);
+			printk("io_thread - write failed, fd = %d, err = %d\n",
+			       kernel_fd, -n);
 	}
 }
 
@@ -571,10 +338,11 @@
 	int pid, fds[2], err;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("start_io_thread - os_pipe failed, errno = %d\n", -err);
-		return(-1);
+	if(err < 0){
+		printk("start_io_thread - os_pipe failed, err = %d\n", -err);
+		goto out;
 	}
+
 	kernel_fd = fds[0];
 	*fd_out = fds[1];
 
@@ -582,32 +350,19 @@
 		    NULL);
 	if(pid < 0){
 		printk("start_io_thread - clone failed : errno = %d\n", errno);
-		return(-errno);
+		goto out_close;
 	}
-	return(pid);
-}
-
-#ifdef notdef
-int start_io_thread(unsigned long sp, int *fd_out)
-{
-	int pid;
 
-	if((kernel_fd = get_pty()) < 0) return(-1);
-	raw(kernel_fd, 0);
-	if((*fd_out = open(ptsname(kernel_fd), O_RDWR)) < 0){
-		printk("Couldn't open tty for IO\n");
-		return(-1);
-	}
-
-	pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
-		    NULL);
-	if(pid < 0){
-		printk("start_io_thread - clone failed : errno = %d\n", errno);
-		return(-errno);
-	}
 	return(pid);
+
+ out_close:
+	os_close_file(fds[0]);
+	os_close_file(fds[1]);
+	kernel_fd = -1;
+	*fd_out = -1;
+ out:
+	return(err);
 }
-#endif
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -Nru a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
--- a/arch/um/drivers/xterm.c	2003-02-05 20:16:02 -08:00
+++ b/arch/um/drivers/xterm.c	2004-08-24 02:08:18 -07:00
@@ -8,7 +8,6 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <termios.h>
 #include <signal.h>
 #include <sched.h>
@@ -36,7 +35,8 @@
 {
 	struct xterm_chan *data;
 
-	if((data = malloc(sizeof(*data))) == NULL) return(NULL);
+	data = malloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct xterm_chan) { .pid 		= -1, 
 				       .helper_pid 	= -1,
 				       .device 		= device, 
@@ -93,7 +93,7 @@
 			 "/usr/lib/uml/port-helper", "-uml-socket",
 			 file, NULL };
 
-	if(access(argv[4], X_OK))
+	if(os_access(argv[4], OS_ACC_X_OK) < 0)
 		argv[4] = "port-helper";
 
 	fd = mkstemp(file);
@@ -106,13 +106,13 @@
 		printk("xterm_open : unlink failed, errno = %d\n", errno);
 		return(-errno);
 	}
-	close(fd);
+	os_close_file(fd);
 
-	fd = create_unix_socket(file, sizeof(file));
+	fd = os_create_unix_socket(file, sizeof(file), 1);
 	if(fd < 0){
 		printk("xterm_open : create_unix_socket failed, errno = %d\n", 
 		       -fd);
-		return(-fd);
+		return(fd);
 	}
 
 	sprintf(title, data->title, data->device);
@@ -128,15 +128,16 @@
 	if(data->direct_rcv)
 		new = os_rcv_fd(fd, &data->helper_pid);
 	else {
-		if((err = os_set_fd_block(fd, 0)) != 0){
+		err = os_set_fd_block(fd, 0);
+		if(err < 0){
 			printk("xterm_open : failed to set descriptor "
-			       "non-blocking, errno = %d\n", err);
+			       "non-blocking, err = %d\n", -err);
 			return(err);
 		}
 		new = xterm_fd(fd, &data->helper_pid);
 	}
 	if(new < 0){
-		printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new);
+		printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
 		goto out;
 	}
 
@@ -160,7 +161,7 @@
 	if(data->helper_pid != -1) 
 		os_kill_process(data->helper_pid, 0);
 	data->helper_pid = -1;
-	close(fd);
+	os_close_file(fd);
 }
 
 void xterm_free(void *d)
diff -Nru a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
--- a/arch/um/drivers/xterm_kern.c	2002-12-28 12:28:00 -08:00
+++ b/arch/um/drivers/xterm_kern.c	2004-08-24 02:08:18 -07:00
@@ -5,9 +5,12 @@
 
 #include "linux/errno.h"
 #include "linux/slab.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
 #include "asm/semaphore.h"
 #include "asm/irq.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "kern_util.h"
 #include "os.h"
 #include "xterm.h"
@@ -19,17 +22,18 @@
 	int new_fd;
 };
 
-static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct xterm_wait *xterm = data;
 	int fd;
 
 	fd = os_rcv_fd(xterm->fd, &xterm->pid);
 	if(fd == -EAGAIN)
-		return;
+		return(IRQ_NONE);
 
 	xterm->new_fd = fd;
 	up(&xterm->sem);
+	return(IRQ_HANDLED);
 }
 
 int xterm_fd(int socket, int *pid_out)
@@ -54,7 +58,8 @@
 	if(err){
 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
 		       "err = %d\n",  err);
-		return(err);
+		ret = err;
+		goto out;
 	}
 	down(&data->sem);
 
@@ -62,6 +67,7 @@
 
 	ret = data->new_fd;
 	*pid_out = data->pid;
+ out:
 	kfree(data);
 
 	return(ret);
diff -Nru a/arch/um/dyn.lds.S b/arch/um/dyn.lds.S
--- a/arch/um/dyn.lds.S	2003-01-17 19:32:24 -08:00
+++ b/arch/um/dyn.lds.S	2004-08-24 02:08:18 -07:00
@@ -1,3 +1,5 @@
+#include <asm-generic/vmlinux.lds.h>
+
 OUTPUT_FORMAT(ELF_FORMAT)
 OUTPUT_ARCH(ELF_ARCH)
 ENTRY(_start)
@@ -10,12 +12,15 @@
 {
   . = START + SIZEOF_HEADERS;
   .interp         : { *(.interp) }
-  . = ALIGN(4096);
   __binary_start = .;
   . = ALIGN(4096);		/* Init code and data */
   _stext = .;
   __init_begin = .;
-  .text.init : { *(.text.init) }
+  .init.text : {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
 
   . = ALIGN(4096);
 
@@ -55,7 +60,9 @@
   } =0x90909090
   .plt            : { *(.plt) }
   .text           : {
-    *(.text .stub .text.* .gnu.linkonce.t.*)
+    *(.text)
+    SCHED_TEXT
+    *(.stub .text.* .gnu.linkonce.t.*)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
   } =0x90909090
@@ -67,7 +74,7 @@
 
   #include "asm/common.lds.S"
 
-  .data.init : { *(.data.init) }
+  init.data : { *(.init.data) }
 
   /* Ensure the __preinit_array_start label is properly aligned.  We
      could instead move the label definition inside the section, but
diff -Nru a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h
--- a/arch/um/include/2_5compat.h	2002-10-14 06:53:49 -07:00
+++ b/arch/um/include/2_5compat.h	2004-08-24 02:08:18 -07:00
@@ -6,20 +6,6 @@
 #ifndef __2_5_COMPAT_H__
 #define __2_5_COMPAT_H__
 
-#include "linux/version.h"
-
-#define INIT_CONSOLE(dev_name, write_proc, device_proc, setup_proc, f) { \
-	name :		dev_name, \
-	write :		write_proc, \
-	read :		NULL, \
-	device :	device_proc, \
-	setup :		setup_proc, \
-	flags :		f, \
-	index :		-1, \
-	cflag :		0, \
-	next :		NULL \
-}
-
 #define INIT_HARDSECT(arr, maj, sizes)
 
 #define SET_PRI(task) do ; while(0)
diff -Nru a/arch/um/include/hostaudio.h b/arch/um/include/hostaudio.h
--- a/arch/um/include/hostaudio.h	2002-09-06 10:29:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,48 +0,0 @@
-/* 
- * Copyright (C) 2002 Steve Schmidtke 
- * Licensed under the GPL
- */
-
-#ifndef HOSTAUDIO_H
-#define HOSTAUDIO_H
-
-#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
-#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
-
-struct hostaudio_state {
-  int fd;
-};
-
-struct hostmixer_state {
-  int fd;
-};
-
-/* UML user-side protoypes */
-extern ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer,
-				   size_t count, loff_t *ppos);
-extern ssize_t hostaudio_write_user(struct hostaudio_state *state, 
-				    const char *buffer, size_t count, 
-				    loff_t *ppos);
-extern int hostaudio_ioctl_user(struct hostaudio_state *state, 
-				unsigned int cmd, unsigned long arg);
-extern int hostaudio_open_user(struct hostaudio_state *state, int r, int w, 
-			       char *dsp);
-extern int hostaudio_release_user(struct hostaudio_state *state);
-extern int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state, 
-				unsigned int cmd, unsigned long arg);
-extern int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, 
-				      int w, char *mixer);
-extern int hostmixer_release_mixdev_user(struct hostmixer_state *state);
-
-#endif /* HOSTAUDIO_H */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/include/irq_kern.h	2004-08-24 11:13:14 -07:00
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __IRQ_KERN_H__
+#define __IRQ_KERN_H__
+
+#include "linux/interrupt.h"
+
+extern int um_request_irq(unsigned int irq, int fd, int type,
+			  irqreturn_t (*handler)(int, void *,
+						 struct pt_regs *),
+			  unsigned long irqflags,  const char * devname,
+			  void *dev_id);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
--- a/arch/um/include/kern_util.h	2004-02-25 02:31:13 -08:00
+++ b/arch/um/include/kern_util.h	2004-08-24 02:08:18 -07:00
@@ -60,12 +60,11 @@
 extern void paging_init(void);
 extern void init_flush_vm(void);
 extern void *syscall_sp(void *t);
-extern void syscall_trace(void);
+extern void syscall_trace(union uml_pt_regs *regs, int entryexit);
 extern int hz(void);
-extern void idle_timer(void);
+extern void uml_idle_timer(void);
 extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
 extern int external_pid(void *t);
-extern int pid_to_processor_id(int pid);
 extern void boot_timer_handler(int sig);
 extern void interrupt_end(void);
 extern void initial_thread_cb(void (*proc)(void *), void *arg);
@@ -89,9 +88,7 @@
 extern char *uml_strdup(char *string);
 extern void unprotect_kernel_mem(void);
 extern void protect_kernel_mem(void);
-extern void set_kmem_end(unsigned long);
 extern void uml_cleanup(void);
-extern int pid_to_processor_id(int pid);
 extern void set_current(void *t);
 extern void lock_signalled_task(void *t);
 extern void IPI_handler(int cpu);
@@ -100,7 +97,9 @@
 extern int clear_user_proc(void *buf, int size);
 extern int copy_to_user_proc(void *to, void *from, int size);
 extern int copy_from_user_proc(void *to, void *from, int size);
+extern int strlen_user_proc(char *str);
 extern void bus_handler(int sig, union uml_pt_regs *regs);
+extern void winch(int sig, union uml_pt_regs *regs);
 extern long execute_syscall(void *r);
 extern int smp_sigio_handler(void);
 extern void *get_current(void);
@@ -111,6 +110,8 @@
 extern void free_irq(unsigned int, void *);
 extern int um_in_interrupt(void);
 extern int cpu(void);
+extern unsigned long long time_stamp(void);
+
 #endif
 
 /*
diff -Nru a/arch/um/include/line.h b/arch/um/include/line.h
--- a/arch/um/include/line.h	2003-06-11 12:33:08 -07:00
+++ b/arch/um/include/line.h	2004-08-24 02:08:18 -07:00
@@ -9,12 +9,14 @@
 #include "linux/list.h"
 #include "linux/workqueue.h"
 #include "linux/tty.h"
+#include "linux/interrupt.h"
 #include "asm/semaphore.h"
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
 struct line_driver {
 	char *name;
+	char *device_name;
 	char *devfs_name;
 	short major;
 	short minor_start;
@@ -67,8 +69,6 @@
 
 #define LINES_INIT(n) {  num :		n }
 
-extern void line_interrupt(int irq, void *data, struct pt_regs *unused);
-extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused);
 extern void line_close(struct line *lines, struct tty_struct *tty);
 extern int line_open(struct line *lines, struct tty_struct *tty, 
 		     struct chan_opts *opts);
diff -Nru a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
--- a/arch/um/include/mconsole.h	2003-01-18 12:29:27 -08:00
+++ b/arch/um/include/mconsole.h	2004-08-24 02:08:18 -07:00
@@ -41,11 +41,13 @@
 
 struct mc_request;
 
+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
+
 struct mconsole_command
 {
 	char *command;
 	void (*handler)(struct mc_request *req);
-	int as_interrupt;
+	enum mc_context context;
 };
 
 struct mc_request
@@ -77,6 +79,8 @@
 extern void mconsole_cad(struct mc_request *req);
 extern void mconsole_stop(struct mc_request *req);
 extern void mconsole_go(struct mc_request *req);
+extern void mconsole_log(struct mc_request *req);
+extern void mconsole_proc(struct mc_request *req);
 
 extern int mconsole_get_request(int fd, struct mc_request *req);
 extern int mconsole_notify(char *sock_name, int type, const void *data, 
diff -Nru a/arch/um/include/mem.h b/arch/um/include/mem.h
--- a/arch/um/include/mem.h	2002-11-22 09:53:07 -08:00
+++ b/arch/um/include/mem.h	2004-08-24 02:08:18 -07:00
@@ -1,19 +1,18 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #ifndef __MEM_H__
 #define __MEM_H__
 
-struct vm_reserved {
-	struct list_head list;
-	unsigned long start;
-	unsigned long end;
-};
+#include "linux/types.h"
 
-extern void set_usable_vm(unsigned long start, unsigned long end);
-extern void set_kmem_end(unsigned long new);
+extern int phys_mapping(unsigned long phys, __u64 *offset_out);
+extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
+extern int is_remapped(void *virt);
+extern int physmem_remove_mapping(void *virt);
+extern void physmem_forget_descriptor(int fd);
 
 #endif
 
diff -Nru a/arch/um/include/mem_kern.h b/arch/um/include/mem_kern.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/include/mem_kern.h	2004-08-24 11:13:14 -07:00
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MEM_KERN_H__
+#define __MEM_KERN_H__
+
+#include "linux/list.h"
+#include "linux/types.h"
+
+struct remapper {
+	struct list_head list;
+	int (*proc)(int, unsigned long, int, __u64);
+};
+
+extern void register_remapper(struct remapper *info);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
--- a/arch/um/include/mem_user.h	2002-11-20 20:04:10 -08:00
+++ b/arch/um/include/mem_user.h	2004-08-24 02:08:18 -07:00
@@ -32,43 +32,38 @@
 #ifndef _MEM_USER_H
 #define _MEM_USER_H
 
-struct mem_region {
+struct iomem_region {
+	struct iomem_region *next;
 	char *driver;
-	unsigned long start_pfn;
-	unsigned long start;
-	unsigned long len;
-	void *mem_map;
 	int fd;
+	int size;
+	unsigned long phys;
+	unsigned long virt;
 };
 
-extern struct mem_region *regions[];
-extern struct mem_region physmem_region;
+extern struct iomem_region *iomem_regions;
+extern int iomem_size;
 
 #define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
 
 extern unsigned long host_task_size;
 extern unsigned long task_size;
 
+extern void check_devanon(void);
 extern int init_mem_user(void);
 extern int create_mem_file(unsigned long len);
-extern void setup_range(int fd, char *driver, unsigned long start,
-			unsigned long pfn, unsigned long total, int need_vm, 
-			struct mem_region *region, void *reserved);
 extern void setup_memory(void *entry);
 extern unsigned long find_iomem(char *driver, unsigned long *len_out);
-extern int init_maps(struct mem_region *region);
-extern int nregions(void);
-extern int reserve_vm(unsigned long start, unsigned long end, void *e);
+extern int init_maps(unsigned long physmem, unsigned long iomem,
+		     unsigned long highmem);
 extern unsigned long get_vm(unsigned long len);
 extern void setup_physmem(unsigned long start, unsigned long usable,
-			  unsigned long len);
-extern int setup_region(struct mem_region *region, void *entry);
+			  unsigned long len, unsigned long highmem);
 extern void add_iomem(char *name, int fd, unsigned long size);
-extern struct mem_region *phys_region(unsigned long phys);
 extern unsigned long phys_offset(unsigned long phys);
 extern void unmap_physmem(void);
-extern int map_memory(unsigned long virt, unsigned long phys, 
-		      unsigned long len, int r, int w, int x);
+extern void map_memory(unsigned long virt, unsigned long phys,
+		       unsigned long len, int r, int w, int x);
 extern int protect_memory(unsigned long addr, unsigned long len, 
 			  int r, int w, int x, int must_succeed);
 extern unsigned long get_kmem_end(void);
diff -Nru a/arch/um/include/os.h b/arch/um/include/os.h
--- a/arch/um/include/os.h	2003-01-18 12:26:19 -08:00
+++ b/arch/um/include/os.h	2004-08-24 02:08:18 -07:00
@@ -17,6 +17,32 @@
 #define OS_TYPE_FIFO 6
 #define OS_TYPE_SOCK 7
 
+/* os_access() flags */
+#define OS_ACC_F_OK    0       /* Test for existence.  */
+#define OS_ACC_X_OK    1       /* Test for execute permission.  */
+#define OS_ACC_W_OK    2       /* Test for write permission.  */
+#define OS_ACC_R_OK    4       /* Test for read permission.  */
+#define OS_ACC_RW_OK   (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */
+
+/*
+ * types taken from stat_file() in hostfs_user.c
+ * (if they are wrong here, they are wrong there...).
+ */
+struct uml_stat {
+	int                ust_dev;        /* device */
+	unsigned long long ust_ino;        /* inode */
+	int                ust_mode;       /* protection */
+	int                ust_nlink;      /* number of hard links */
+	int                ust_uid;        /* user ID of owner */
+	int                ust_gid;        /* group ID of owner */
+	unsigned long long ust_size;       /* total size, in bytes */
+	int                ust_blksize;    /* blocksize for filesystem I/O */
+	unsigned long long ust_blocks;     /* number of blocks allocated */
+	unsigned long      ust_atime;      /* time of last access */
+	unsigned long      ust_mtime;      /* time of last modification */
+	unsigned long      ust_ctime;      /* time of last change */
+};
+
 struct openflags {
 	unsigned int r : 1;
 	unsigned int w : 1;
@@ -84,29 +110,47 @@
 	flags.e = 1; 
 	return(flags); 
 }
- 
+
 static inline struct openflags of_cloexec(struct openflags flags)
 { 
 	flags.cl = 1; 
 	return(flags); 
 }
   
+extern int os_stat_file(const char *file_name, struct uml_stat *buf);
+extern int os_stat_fd(const int fd, struct uml_stat *buf);
+extern int os_access(const char *file, int mode);
+extern void os_print_error(int error, const char* str);
+extern int os_get_exec_close(int fd, int *close_on_exec);
+extern int os_set_exec_close(int fd, int close_on_exec);
+extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
+extern int os_window_size(int fd, int *rows, int *cols);
+extern int os_new_tty_pgrp(int fd, int pid);
+extern int os_get_ifname(int fd, char *namebuf);
+extern int os_set_slip(int fd);
+extern int os_set_owner(int fd, int pid);
+extern int os_sigio_async(int master, int slave);
+extern int os_mode_fd(int fd, int mode);
+
 extern int os_seek_file(int fd, __u64 offset);
 extern int os_open_file(char *file, struct openflags flags, int mode);
 extern int os_read_file(int fd, void *buf, int len);
-extern int os_write_file(int fd, void *buf, int count);
+extern int os_write_file(int fd, const void *buf, int count);
 extern int os_file_size(char *file, long long *size_out);
+extern int os_file_modtime(char *file, unsigned long *modtime);
 extern int os_pipe(int *fd, int stream, int close_on_exec);
 extern int os_set_fd_async(int fd, int owner);
 extern int os_set_fd_block(int fd, int blocking);
 extern int os_accept_connection(int fd);
+extern int os_create_unix_socket(char *file, int len, int close_on_exec);
 extern int os_shutdown_socket(int fd, int r, int w);
 extern void os_close_file(int fd);
 extern int os_rcv_fd(int fd, int *helper_pid_out);
-extern int create_unix_socket(char *file, int len);
+extern int create_unix_socket(char *file, int len, int close_on_exec);
 extern int os_connect_socket(char *name);
 extern int os_file_type(char *file);
 extern int os_file_mode(char *file, struct openflags *mode_out);
+extern int os_lock_file(int fd, int excl);
 
 extern unsigned long os_process_pc(int pid);
 extern int os_process_parent(int pid);
@@ -115,11 +159,12 @@
 extern void os_usr1_process(int pid);
 extern int os_getpid(void);
 
-extern int os_map_memory(void *virt, int fd, unsigned long off, 
+extern int os_map_memory(void *virt, int fd, unsigned long long off,
 			 unsigned long len, int r, int w, int x);
 extern int os_protect_memory(void *addr, unsigned long len, 
 			     int r, int w, int x);
 extern int os_unmap_memory(void *addr, int len);
+extern void os_flush_stdout(void);
 
 #endif
 
diff -Nru a/arch/um/include/signal_user.h b/arch/um/include/signal_user.h
--- a/arch/um/include/signal_user.h	2002-09-06 10:29:28 -07:00
+++ b/arch/um/include/signal_user.h	2004-08-24 02:08:18 -07:00
@@ -11,6 +11,8 @@
 extern int change_sig(int signal, int on);
 extern void set_sigstack(void *stack, int size);
 extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern int set_signals(int enable);
+extern int get_signals(void);
 
 #endif
 
diff -Nru a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h
--- a/arch/um/include/skas_ptrace.h	2003-02-05 20:16:02 -08:00
+++ b/arch/um/include/skas_ptrace.h	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 
diff -Nru a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
--- a/arch/um/include/sysdep-i386/checksum.h	2003-02-18 10:38:27 -08:00
+++ b/arch/um/include/sysdep-i386/checksum.h	2004-08-24 02:08:22 -07:00
@@ -5,6 +5,7 @@
 #ifndef __UM_SYSDEP_CHECKSUM_H
 #define __UM_SYSDEP_CHECKSUM_H
 
+#include "linux/in6.h"
 #include "linux/string.h"
 
 /*
diff -Nru a/arch/um/include/sysdep-i386/frame_user.h b/arch/um/include/sysdep-i386/frame_user.h
--- a/arch/um/include/sysdep-i386/frame_user.h	2002-12-29 17:05:47 -08:00
+++ b/arch/um/include/sysdep-i386/frame_user.h	2004-08-24 02:08:18 -07:00
@@ -56,26 +56,26 @@
  * it would have to be __builtin_frame_address(1).
  */
 
-static inline unsigned long frame_restorer(void)
-{
-	unsigned long *fp;
-
-	fp = __builtin_frame_address(0);
-	return((unsigned long) (fp + 1));
-}
+#define frame_restorer() \
+({ \
+	unsigned long *fp; \
+\
+	fp = __builtin_frame_address(0); \
+	((unsigned long) (fp + 1)); \
+})
 
 /* Similarly, this returns the value of sp when the handler was first
  * entered.  This is used to calculate the proper sp when delivering
  * signals.
  */
 
-static inline unsigned long frame_sp(void)
-{
-	unsigned long *fp;
-
-	fp = __builtin_frame_address(0);
-	return((unsigned long) (fp + 1));
-}
+#define frame_sp() \
+({ \
+	unsigned long *fp; \
+\
+	fp = __builtin_frame_address(0); \
+	((unsigned long) (fp + 1)); \
+})
 
 #endif
 
diff -Nru a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
--- a/arch/um/include/sysdep-i386/sigcontext.h	2002-12-29 17:05:47 -08:00
+++ b/arch/um/include/sysdep-i386/sigcontext.h	2004-08-24 02:08:18 -07:00
@@ -28,8 +28,8 @@
  */
 #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
 
-/* These are General Protection and Page Fault */
-#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14))
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(trap) (trap == 14)
 
 #define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
 
diff -Nru a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
--- a/arch/um/include/sysdep-i386/syscalls.h	2002-12-29 17:05:47 -08:00
+++ b/arch/um/include/sysdep-i386/syscalls.h	2004-08-24 02:08:18 -07:00
@@ -11,39 +11,34 @@
 #define EXECUTE_SYSCALL(syscall, regs) \
 	((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
 
-extern syscall_handler_t sys_modify_ldt;
-extern syscall_handler_t old_mmap_i386;
-extern syscall_handler_t old_select;
-extern syscall_handler_t sys_ni_syscall;
-
 #define ARCH_SYSCALLS \
-	[ __NR_mmap ] = old_mmap_i386, \
-	[ __NR_select ] = old_select, \
-	[ __NR_vm86old ] = sys_ni_syscall, \
-        [ __NR_modify_ldt ] = sys_modify_ldt, \
-	[ __NR_lchown32 ] = sys_lchown, \
-	[ __NR_getuid32 ] = sys_getuid, \
-	[ __NR_getgid32 ] = sys_getgid, \
-	[ __NR_geteuid32 ] = sys_geteuid, \
-	[ __NR_getegid32 ] = sys_getegid, \
-	[ __NR_setreuid32 ] = sys_setreuid, \
-	[ __NR_setregid32 ] = sys_setregid, \
-	[ __NR_getgroups32 ] = sys_getgroups, \
-	[ __NR_setgroups32 ] = sys_setgroups, \
-	[ __NR_fchown32 ] = sys_fchown, \
-	[ __NR_setresuid32 ] = sys_setresuid, \
-	[ __NR_getresuid32 ] = sys_getresuid, \
-	[ __NR_setresgid32 ] = sys_setresgid, \
-	[ __NR_getresgid32 ] = sys_getresgid, \
-	[ __NR_chown32 ] = sys_chown, \
-	[ __NR_setuid32 ] = sys_setuid, \
-	[ __NR_setgid32 ] = sys_setgid, \
-	[ __NR_setfsuid32 ] = sys_setfsuid, \
-	[ __NR_setfsgid32 ] = sys_setfsgid, \
-	[ __NR_pivot_root ] = sys_pivot_root, \
-	[ __NR_mincore ] = sys_mincore, \
-	[ __NR_madvise ] = sys_madvise, \
-        [ 222 ] = sys_ni_syscall, 
+	[ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \
+	[ __NR_select ] = (syscall_handler_t *) old_select, \
+	[ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
+        [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
+	[ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
+	[ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
+	[ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
+	[ __NR_geteuid32 ] = (syscall_handler_t *) sys_geteuid, \
+	[ __NR_getegid32 ] = (syscall_handler_t *) sys_getegid, \
+	[ __NR_setreuid32 ] = (syscall_handler_t *) sys_setreuid, \
+	[ __NR_setregid32 ] = (syscall_handler_t *) sys_setregid, \
+	[ __NR_getgroups32 ] = (syscall_handler_t *) sys_getgroups, \
+	[ __NR_setgroups32 ] = (syscall_handler_t *) sys_setgroups, \
+	[ __NR_fchown32 ] = (syscall_handler_t *) sys_fchown, \
+	[ __NR_setresuid32 ] = (syscall_handler_t *) sys_setresuid, \
+	[ __NR_getresuid32 ] = (syscall_handler_t *) sys_getresuid, \
+	[ __NR_setresgid32 ] = (syscall_handler_t *) sys_setresgid, \
+	[ __NR_getresgid32 ] = (syscall_handler_t *) sys_getresgid, \
+	[ __NR_chown32 ] = (syscall_handler_t *) sys_chown, \
+	[ __NR_setuid32 ] = (syscall_handler_t *) sys_setuid, \
+	[ __NR_setgid32 ] = (syscall_handler_t *) sys_setgid, \
+	[ __NR_setfsuid32 ] = (syscall_handler_t *) sys_setfsuid, \
+	[ __NR_setfsgid32 ] = (syscall_handler_t *) sys_setfsgid, \
+	[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
+	[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
+	[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
+        [ 222 ] = (syscall_handler_t *) sys_ni_syscall,
         
 /* 222 doesn't yet have a name in include/asm-i386/unistd.h */
 
diff -Nru a/arch/um/include/ubd_user.h b/arch/um/include/ubd_user.h
--- a/arch/um/include/ubd_user.h	2002-09-06 10:29:28 -07:00
+++ b/arch/um/include/ubd_user.h	2004-08-24 02:08:18 -07:00
@@ -9,7 +9,7 @@
 
 #include "os.h"
 
-enum ubd_req { UBD_READ, UBD_WRITE };
+enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
 
 struct io_thread_req {
 	enum ubd_req op;
@@ -20,8 +20,10 @@
 	char *buffer;
 	int sectorsize;
 	unsigned long sector_mask;
-	unsigned long cow_offset;
+	unsigned long long cow_offset;
 	unsigned long bitmap_words[2];
+	int map_fd;
+	unsigned long long map_offset;
 	int error;
 };
 
@@ -31,7 +33,7 @@
 			 int *create_cow_out);
 extern int create_cow_file(char *cow_file, char *backing_file, 
 			   struct openflags flags, int sectorsize, 
-			   int *bitmap_offset_out, 
+			   int alignment, int *bitmap_offset_out,
 			   unsigned long *bitmap_len_out,
 			   int *data_offset_out);
 extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
@@ -39,7 +41,6 @@
 extern int write_ubd_fs(int fd, char *buffer, int len);
 extern int start_io_thread(unsigned long sp, int *fds_out);
 extern void do_io(struct io_thread_req *req);
-extern int ubd_is_dir(char *file);
 
 static inline int ubd_test_bit(__u64 bit, unsigned char *data)
 {
diff -Nru a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
--- a/arch/um/include/um_uaccess.h	2002-11-21 18:38:50 -08:00
+++ b/arch/um/include/um_uaccess.h	2004-08-24 02:08:18 -07:00
@@ -38,22 +38,73 @@
 				from, n));
 }
 
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+
 static inline int strncpy_from_user(char *dst, const char *src, int count)
 {
 	return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas,
 				dst, src, count));
 }
 
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
 static inline int __clear_user(void *mem, int len)
 {
 	return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len));
 }
 
+/*
+ * clear_user: - Zero a block of memory in user space.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
 static inline int clear_user(void *mem, int len)
 {
 	return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len));
 }
 
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ * @n:   The maximum valid length
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
 static inline int strnlen_user(const void *str, int len)
 {
 	return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len));
diff -Nru a/arch/um/include/user.h b/arch/um/include/user.h
--- a/arch/um/include/user.h	2002-09-06 10:29:28 -07:00
+++ b/arch/um/include/user.h	2004-08-24 02:08:28 -07:00
@@ -14,6 +14,9 @@
 extern void kfree(void *ptr);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
+extern int strlcpy(char *, const char *, int);
+extern void *um_vmalloc(int size);
+extern void vfree(void *ptr);
 
 #endif
 
diff -Nru a/arch/um/include/user_util.h b/arch/um/include/user_util.h
--- a/arch/um/include/user_util.h	2003-02-05 07:18:58 -08:00
+++ b/arch/um/include/user_util.h	2004-08-24 02:08:27 -07:00
@@ -14,8 +14,6 @@
 extern int unlockpt(int __fd);
 extern char *ptsname(int __fd);
 
-enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-
 struct cpu_task {
 	int pid;
 	void *task;
@@ -59,13 +57,11 @@
 extern void *add_signal_handler(int sig, void (*handler)(int));
 extern int start_fork_tramp(void *arg, unsigned long temp_stack, 
 			    int clone_flags, int (*tramp)(void *));
-extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
 extern int linux_main(int argc, char **argv);
 extern void set_cmdline(char *cmd);
 extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
 extern int get_pty(void);
 extern void *um_kmalloc(int size);
-extern int raw(int fd, int complain);
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
 extern void setup_machinename(char *machine_out);
 extern void setup_hostinfo(void);
@@ -86,11 +82,17 @@
 extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
 extern void write_sigio_workaround(void);
 extern void arch_check_bugs(void);
+extern int cpu_feature(char *what, char *buf, int len);
 extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
 extern int arch_fixup(unsigned long address, void *sc_ptr);
 extern void forward_pending_sigio(int target);
 extern int can_do_skas(void);
- 
+extern void arch_init_thread(void);
+
+extern int __raw(int fd, int complain, int now);
+#define raw(fd, complain) __raw((fd), (complain), 1)
+
+#define CATCH_EINTR(expr) while ( ((expr) < 0) && errno == EINTR)
 #endif
 
 /*
diff -Nru a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
--- a/arch/um/kernel/Makefile	2004-08-15 11:20:44 -07:00
+++ b/arch/um/kernel/Makefile	2004-08-24 02:08:30 -07:00
@@ -3,15 +3,15 @@
 # Licensed under the GPL
 #
 
-extra-y := vmlinux.lds
+extra-y := vmlinux.lds uml.lds
 
 obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \
-	helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \
-	process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
-	sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o \
-	syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \
-	time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
-	umid.o user_syms.o user_util.o
+	helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
+	physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
+	sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
+	syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \
+	time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
+	um_arch.o umid.o user_util.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
@@ -24,43 +24,27 @@
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
 USER_OBJS := $(filter %_user.o,$(obj-y))  $(user-objs-y) config.o helper.o \
-	process.o tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o
+	main.o process.o tempfile.o time.o tty_log.o umid.o user_util.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
-DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
-
-
-CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \
-	-I/usr/include -I../include
-
 CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS))
 
-$(USER_OBJS) : %.o: %.c
-	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
 # This has to be separate because it needs be compiled with frame pointers
 # regardless of how the rest of the kernel is built.
 
 $(obj)/frame.o: $(src)/frame.c
 	$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
 
-QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
+$(USER_OBJS) : %.o: %.c
+	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
 
-$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
-	$(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
 
 $(obj)/config.o : $(obj)/config.c
 
-clean:
-	rm -f config.c
-	for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
-
-modules:
-
-fastdep:
-
-dep:
-
-archmrproper: clean
+quiet_cmd_quote = QUOTE $@
+cmd_quote = $(PERL) -e $(QUOTE) < $< > $@
 
+targets += config.c
+$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config FORCE
+	$(call if_changed,quote)
diff -Nru a/arch/um/kernel/config.c.in b/arch/um/kernel/config.c.in
--- a/arch/um/kernel/config.c.in	2002-09-06 10:29:28 -07:00
+++ b/arch/um/kernel/config.c.in	2004-08-24 02:08:18 -07:00
@@ -7,9 +7,7 @@
 #include <stdlib.h>
 #include "init.h"
 
-static __initdata char *config = "
-CONFIG
-";
+static __initdata char *config = "CONFIG";
 
 static int __init print_config(char *line, int *add)
 {
diff -Nru a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
--- a/arch/um/kernel/exec_kern.c	2003-02-15 19:30:17 -08:00
+++ b/arch/um/kernel/exec_kern.c	2004-08-24 02:08:18 -07:00
@@ -32,10 +32,15 @@
 	CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
 }
 
+extern void log_exec(char **argv, void *tty);
+
 static int execve1(char *file, char **argv, char **env)
 {
         int error;
 
+#ifdef CONFIG_TTY_LOG
+	log_exec(argv, current->tty);
+#endif
         error = do_execve(file, argv, env, &current->thread.regs);
         if (error == 0){
                 current->ptrace &= ~PT_DTRACE;
diff -Nru a/arch/um/kernel/frame.c b/arch/um/kernel/frame.c
--- a/arch/um/kernel/frame.c	2003-02-05 07:18:58 -08:00
+++ b/arch/um/kernel/frame.c	2004-08-24 02:08:27 -07:00
@@ -21,6 +21,7 @@
 #include "sysdep/sigcontext.h"
 #include "frame_user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "ptrace_user.h"
 #include "os.h"
 
@@ -40,7 +41,7 @@
 	/* Wait for it to stop itself and continue it with a SIGUSR1 to force 
 	 * it into the signal handler.
 	 */
-	n = waitpid(pid, &status, WUNTRACED);
+	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0){
 		printf("capture_stack : waitpid failed - errno = %d\n", errno);
 		exit(1);
@@ -60,7 +61,7 @@
 	 * At this point, the handler has stuffed the addresses of
 	 * sig, sc, and SA_RESTORER in raw.
 	 */
-	n = waitpid(pid, &status, WUNTRACED);
+	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0){
 		printf("capture_stack : waitpid failed - errno = %d\n", errno);
 		exit(1);
@@ -82,7 +83,8 @@
 		       errno);
 		exit(1);
 	}
-	if(waitpid(pid, &status, 0) < 0){
+	CATCH_EINTR(n = waitpid(pid, &status, 0));
+	if(n < 0){
 		printf("capture_stack : waitpid failed - errno = %d\n", errno);
 		exit(1);
 	}
@@ -279,7 +281,7 @@
 	struct sc_frame_raw raw_sc;
 	struct si_frame_raw raw_si;
 	void *stack, *sigstack;
-	unsigned long top, sig_top, base;
+	unsigned long top, base;
 
 	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -292,7 +294,6 @@
 	}
 
 	top = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
-	sig_top = (unsigned long) sigstack + PAGE_SIZE;
 
 	/* Get the sigcontext, no sigrestorer layout */
 	raw_sc.restorer = 0;
diff -Nru a/arch/um/kernel/frame_kern.c b/arch/um/kernel/frame_kern.c
--- a/arch/um/kernel/frame_kern.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/frame_kern.c	2004-08-24 02:08:18 -07:00
@@ -6,7 +6,6 @@
 #include "asm/ptrace.h"
 #include "asm/uaccess.h"
 #include "asm/signal.h"
-#include "asm/uaccess.h"
 #include "asm/ucontext.h"
 #include "frame_kern.h"
 #include "sigcontext.h"
@@ -29,12 +28,15 @@
 			    sizeof(restorer)));
 }
 
+extern int userspace_pid[];
+
 static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, 
 			   struct arch_frame_data *arch)
 {
 	return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 
 					      arch),
-			   copy_sc_to_user_skas(to, fp, &from->regs,
+			   copy_sc_to_user_skas(userspace_pid[0], to, fp,
+						&from->regs,
 						current->thread.cr2,
 						current->thread.err)));
 }
diff -Nru a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c
--- a/arch/um/kernel/helper.c	2003-02-05 20:16:02 -08:00
+++ b/arch/um/kernel/helper.c	2004-08-24 02:08:27 -07:00
@@ -7,12 +7,12 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sched.h>
 #include <sys/signal.h>
 #include <sys/wait.h>
 #include "user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "os.h"
 
 struct helper_data {
@@ -33,6 +33,7 @@
 {
 	struct helper_data *data = arg;
 	char **argv = data->argv;
+	int errval;
 
 	if(helper_pause){
 		signal(SIGHUP, helper_hup);
@@ -41,8 +42,9 @@
 	if(data->pre_exec != NULL)
 		(*data->pre_exec)(data->pre_data);
 	execvp(argv[0], argv);
+	errval = errno;
 	printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
-	write(data->fd, &errno, sizeof(errno));
+	os_write_file(data->fd, &errval, sizeof(errval));
 	os_kill_process(os_getpid(), 0);
 	return(0);
 }
@@ -59,17 +61,20 @@
 	if((stack_out != NULL) && (*stack_out != 0))
 		stack = *stack_out;
 	else stack = alloc_stack(0, um_in_interrupt());
-	if(stack == 0) return(-ENOMEM);
+	if(stack == 0)
+		return(-ENOMEM);
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("run_helper : pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("run_helper : pipe failed, err = %d\n", -err);
+		goto out_free;
 	}
-	if(fcntl(fds[1], F_SETFD, 1) != 0){
-		printk("run_helper : setting FD_CLOEXEC failed, errno = %d\n",
-		       errno);
-		return(-errno);
+
+	err = os_set_exec_close(fds[1], 1);
+	if(err < 0){
+		printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
+		       -err);
+		goto out_close;
 	}
 
 	sp = stack + page_size() - sizeof(void *);
@@ -80,23 +85,34 @@
 	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
 	if(pid < 0){
 		printk("run_helper : clone failed, errno = %d\n", errno);
-		return(-errno);
+		err = -errno;
+		goto out_close;
 	}
-	close(fds[1]);
-	n = read(fds[0], &err, sizeof(err));
+
+	os_close_file(fds[1]);
+	n = os_read_file(fds[0], &err, sizeof(err));
 	if(n < 0){
-		printk("run_helper : read on pipe failed, errno = %d\n", 
-		       errno);
-		return(-errno);
+		printk("run_helper : read on pipe failed, err = %d\n", -n);
+		err = n;
+		goto out_kill;
 	}
 	else if(n != 0){
-		waitpid(pid, NULL, 0);
-		pid = -err;
+		CATCH_EINTR(n = waitpid(pid, NULL, 0));
+		pid = -errno;
 	}
 
 	if(stack_out == NULL) free_stack(stack, 0);
         else *stack_out = stack;
 	return(pid);
+
+ out_kill:
+	os_kill_process(pid, 1);
+ out_close:
+	os_close_file(fds[0]);
+	os_close_file(fds[1]);
+ out_free:
+	free_stack(stack, 0);
+	return(err);
 }
 
 int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, 
@@ -117,9 +133,11 @@
 	}
 	if(stack_out == NULL){
 		pid = waitpid(pid, &status, 0);
-		if(pid < 0)
+		if(pid < 0){
 			printk("run_helper_thread - wait failed, errno = %d\n",
-			       pid);
+			       errno);
+			pid = -errno;
+		}
 		if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
 			printk("run_helper_thread - thread returned status "
 			       "0x%x\n", status);
diff -Nru a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
--- a/arch/um/kernel/init_task.c	2004-06-17 23:41:39 -07:00
+++ b/arch/um/kernel/init_task.c	2004-08-24 02:08:18 -07:00
@@ -8,7 +8,6 @@
 #include "linux/module.h"
 #include "linux/sched.h"
 #include "linux/init_task.h"
-#include "linux/version.h"
 #include "linux/mqueue.h"
 #include "asm/uaccess.h"
 #include "asm/pgtable.h"
@@ -19,7 +18,7 @@
 struct mm_struct init_mm = INIT_MM(init_mm);
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 EXPORT_SYMBOL(init_mm);
 
 /*
@@ -44,24 +43,10 @@
 __attribute__((__section__(".data.init_task"))) = 
 { INIT_THREAD_INFO(init_task) };
 
-struct task_struct *alloc_task_struct(void)
-{
-	return((struct task_struct *) 
-	       __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER));
-}
-
 void unprotect_stack(unsigned long stack)
 {
 	protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, 
 		       1, 1, 0, 1);
-}
-
-void free_task_struct(struct task_struct *task)
-{
-	/* free_pages decrements the page counter and only actually frees
-	 * the pages if they are now not accessed by anything.
-	 */
-	free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER);
 }
 
 /*
diff -Nru a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c
--- a/arch/um/kernel/initrd_user.c	2002-09-06 10:29:28 -07:00
+++ b/arch/um/kernel/initrd_user.c	2004-08-24 02:08:18 -07:00
@@ -6,7 +6,6 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
 #include <errno.h>
 
 #include "user_util.h"
@@ -19,13 +18,15 @@
 {
 	int fd, n;
 
-	if((fd = os_open_file(filename, of_read(OPENFLAGS()), 0)) < 0){
-		printk("Opening '%s' failed - errno = %d\n", filename, errno);
+	fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Opening '%s' failed - err = %d\n", filename, -fd);
 		return(-1);
 	}
-	if((n = read(fd, buf, size)) != size){
-		printk("Read of %d bytes from '%s' returned %d, errno = %d\n",
-		       size, filename, n, errno);
+	n = os_read_file(fd, buf, size);
+	if(n != size){
+		printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+		       filename, -n);
 		return(-1);
 	}
 	return(0);
diff -Nru a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
--- a/arch/um/kernel/irq.c	2004-06-24 01:55:53 -07:00
+++ b/arch/um/kernel/irq.c	2004-08-26 23:30:30 -07:00
@@ -18,6 +18,7 @@
 #include "linux/proc_fs.h"
 #include "linux/init.h"
 #include "linux/seq_file.h"
+#include "linux/profile.h"
 #include "asm/irq.h"
 #include "asm/hw_irq.h"
 #include "asm/hardirq.h"
@@ -29,6 +30,7 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 static void register_irq_proc (unsigned int irq);
 
@@ -83,65 +85,55 @@
 	end_none
 };
 
-/* Not changed */
-volatile unsigned long irq_err_count;
-
 /*
  * Generic, controller-independent functions:
  */
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
-	unsigned long flags;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
-	char *p = buf;
+	unsigned long flags;
 
-	p += sprintf(p, "           ");
-	for (j=0; j<num_online_cpus(); j++)
-		p += sprintf(p, "CPU%d       ",j);
-	*p++ = '\n';
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			goto end;
-		p += sprintf(p, "%3d: ",i);
+			goto skip;
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for (j = 0; j < num_online_cpus(); j++)
-			p += sprintf(p, "%10u ",
-				kstat_cpu(cpu_logical_map(j)).irqs[i]);
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-			p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
-	end:
+			seq_printf(p, ", %s", action->name);
+
+		seq_putc(p, '\n');
+skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+	} else if (i == NR_IRQS) {
+		seq_printf(p, "NMI: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", nmi_count(j));
+		seq_putc(p, '\n');
 	}
-	p += sprintf(p, "\n");
-#ifdef notdef
-#ifdef CONFIG_SMP
-	p += sprintf(p, "LOC: ");
-	for (j = 0; j < num_online_cpus(); j++)
-		p += sprintf(p, "%10u ",
-			apic_timer_irqs[cpu_logical_map(j)]);
-	p += sprintf(p, "\n");
-#endif
-#endif
-	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
-	return p - buf;
-}
 
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	return(0);
+	return 0;
 }
 
 /*
@@ -282,13 +274,12 @@
 	 * 0 return value means that this irq is already being
 	 * handled by some other CPU. (or is disabled)
 	 */
-	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
 	unsigned int status;
 
 	irq_enter();
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_this_cpu.irqs[irq]++;
 	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
 	/*
@@ -385,7 +376,7 @@
  */
  
 int request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		unsigned long irqflags, 
 		const char * devname,
 		void *dev_id)
@@ -433,15 +424,19 @@
 EXPORT_SYMBOL(request_irq);
 
 int um_request_irq(unsigned int irq, int fd, int type,
-		   void (*handler)(int, void *, struct pt_regs *),
+		   irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		   unsigned long irqflags, const char * devname,
 		   void *dev_id)
 {
-	int retval;
+	int err;
 
-	retval = request_irq(irq, handler, irqflags, devname, dev_id);
-	if(retval) return(retval);
-	return(activate_fd(irq, fd, type, dev_id));
+	err = request_irq(irq, handler, irqflags, devname, dev_id);
+	if(err)
+		return(err);
+
+	if(fd != -1)
+		err = activate_fd(irq, fd, type, dev_id);
+	return(err);
 }
 
 /* this was setup_x86_irq but it seems pretty generic */
@@ -474,7 +469,8 @@
 	 */
 	spin_lock_irqsave(&desc->lock,flags);
 	p = &desc->action;
-	if ((old = *p) != NULL) {
+	old = *p;
+	if (old != NULL) {
 		/* Can't share interrupts unless both agree to */
 		if (!(old->flags & new->flags & SA_SHIRQ)) {
 			spin_unlock_irqrestore(&desc->lock,flags);
@@ -586,12 +582,14 @@
 					unsigned long count, void *data)
 {
 	int irq = (long) data, full_count = count, err;
-	cpumask_t new_value, tmp;
+	cpumask_t new_value;
 
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
 	err = cpumask_parse(buffer, count, new_value);
+	if(err)
+		return(err);
 
 #ifdef CONFIG_SMP
 	/*
@@ -599,9 +597,11 @@
 	 * way to make the system unusable accidentally :-) At least
 	 * one online CPU still has to be targeted.
 	 */
-	cpus_and(tmp, new_value, cpu_online_map);
-	if (cpus_empty(tmp))
-		return -EINVAL;
+	{ cpumask_t tmp;
+	  cpus_and(tmp, new_value, cpu_online_map);
+	  if (cpus_empty(tmp))
+		  return -EINVAL;
+	}
 #endif
 
 	irq_affinity[irq] = new_value;
@@ -610,30 +610,6 @@
 	return full_count;
 }
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data, new_value;
-	unsigned long full_count = count, err;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -662,24 +638,15 @@
 	smp_affinity_entry[irq] = entry;
 }
 
-/* Read and written as a long */
-cpumask_t prof_cpu_mask = CPU_MASK_ALL;
-
 void __init init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", 0);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff -Nru a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
--- a/arch/um/kernel/irq_user.c	2003-02-05 07:18:58 -08:00
+++ b/arch/um/kernel/irq_user.c	2004-08-24 02:08:18 -07:00
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <signal.h>
 #include <string.h>
 #include <sys/poll.h>
@@ -49,7 +48,8 @@
 
 	if(smp_sigio_handler()) return;
 	while(1){
-		if((n = poll(pollfds, pollfds_num, 0)) < 0){
+		n = poll(pollfds, pollfds_num, 0);
+		if(n < 0){
 			if(errno == EINTR) continue;
 			printk("sigio_handler : poll returned %d, "
 			       "errno = %d\n", n, errno);
@@ -366,34 +366,31 @@
 
 void forward_ipi(int fd, int pid)
 {
-	if(fcntl(fd, F_SETOWN, pid) < 0){
-		int save_errno = errno;
-		if(fcntl(fd, F_GETOWN, 0) != pid){
-			printk("forward_ipi: F_SETOWN failed, fd = %d, "
-			       "me = %d, target = %d, errno = %d\n", fd, 
-			       os_getpid(), pid, save_errno);
-		}
-	}
+	int err;
+
+	err = os_set_owner(fd, pid);
+	if(err < 0)
+		printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
+		       "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
 }
 
 void forward_interrupts(int pid)
 {
 	struct irq_fd *irq;
 	unsigned long flags;
+	int err;
 
 	flags = irq_lock();
 	for(irq=active_fds;irq != NULL;irq = irq->next){
-		if(fcntl(irq->fd, F_SETOWN, pid) < 0){
-			int save_errno = errno;
-			if(fcntl(irq->fd, F_GETOWN, 0) != pid){
-				/* XXX Just remove the irq rather than
-				 * print out an infinite stream of these
-				 */
-				printk("Failed to forward %d to pid %d, "
-				       "errno = %d\n", irq->fd, pid, 
-				       save_errno);
-			}
+		err = os_set_owner(irq->fd, pid);
+		if(err < 0){
+			/* XXX Just remove the irq rather than
+			 * print out an infinite stream of these
+			 */
+			printk("Failed to forward %d to pid %d, err = %d\n",
+			       irq->fd, pid, -err);
 		}
+
 		irq->pid = pid;
 	}
 	irq_unlock(flags);
diff -Nru a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
--- a/arch/um/kernel/ksyms.c	2003-02-05 20:16:02 -08:00
+++ b/arch/um/kernel/ksyms.c	2004-08-24 02:08:27 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -8,7 +8,7 @@
 #include "linux/string.h"
 #include "linux/smp_lock.h"
 #include "linux/spinlock.h"
-#include <linux/highmem.h>
+#include "linux/highmem.h"
 #include "asm/current.h"
 #include "asm/delay.h"
 #include "asm/processor.h"
@@ -19,6 +19,7 @@
 #include "asm/tlbflush.h"
 #include "kern_util.h"
 #include "user_util.h"
+#include "mem_user.h"
 #include "os.h"
 #include "helper.h"
 
@@ -34,34 +35,66 @@
 EXPORT_SYMBOL(flush_tlb_range);
 EXPORT_SYMBOL(host_task_size);
 EXPORT_SYMBOL(arch_validate);
+EXPORT_SYMBOL(get_kmem_end);
 
-EXPORT_SYMBOL(region_pa);
-EXPORT_SYMBOL(region_va);
-EXPORT_SYMBOL(phys_mem_map);
-EXPORT_SYMBOL(page_mem_map);
 EXPORT_SYMBOL(page_to_phys);
 EXPORT_SYMBOL(phys_to_page);
 EXPORT_SYMBOL(high_physmem);
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(um_virt_to_phys);
+EXPORT_SYMBOL(__virt_to_page);
+EXPORT_SYMBOL(to_phys);
+EXPORT_SYMBOL(to_virt);
 EXPORT_SYMBOL(mode_tt);
 EXPORT_SYMBOL(handle_page_fault);
+EXPORT_SYMBOL(find_iomem);
 
+#ifdef CONFIG_MODE_TT
+EXPORT_SYMBOL(strncpy_from_user_tt);
+EXPORT_SYMBOL(copy_from_user_tt);
+EXPORT_SYMBOL(copy_to_user_tt);
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+EXPORT_SYMBOL(strncpy_from_user_skas);
+EXPORT_SYMBOL(copy_to_user_skas);
+EXPORT_SYMBOL(copy_from_user_skas);
+#endif
+
+EXPORT_SYMBOL(os_stat_fd);
+EXPORT_SYMBOL(os_stat_file);
+EXPORT_SYMBOL(os_access);
+EXPORT_SYMBOL(os_print_error);
+EXPORT_SYMBOL(os_get_exec_close);
+EXPORT_SYMBOL(os_set_exec_close);
 EXPORT_SYMBOL(os_getpid);
 EXPORT_SYMBOL(os_open_file);
 EXPORT_SYMBOL(os_read_file);
 EXPORT_SYMBOL(os_write_file);
 EXPORT_SYMBOL(os_seek_file);
+EXPORT_SYMBOL(os_lock_file);
+EXPORT_SYMBOL(os_ioctl_generic);
 EXPORT_SYMBOL(os_pipe);
 EXPORT_SYMBOL(os_file_type);
+EXPORT_SYMBOL(os_file_mode);
+EXPORT_SYMBOL(os_file_size);
+EXPORT_SYMBOL(os_flush_stdout);
 EXPORT_SYMBOL(os_close_file);
+EXPORT_SYMBOL(os_set_fd_async);
+EXPORT_SYMBOL(os_set_fd_block);
 EXPORT_SYMBOL(helper_wait);
 EXPORT_SYMBOL(os_shutdown_socket);
+EXPORT_SYMBOL(os_create_unix_socket);
 EXPORT_SYMBOL(os_connect_socket);
+EXPORT_SYMBOL(os_accept_connection);
+EXPORT_SYMBOL(os_rcv_fd);
 EXPORT_SYMBOL(run_helper);
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(dump_thread);
 
+EXPORT_SYMBOL(do_gettimeofday);
+EXPORT_SYMBOL(do_settimeofday);
+
 /* This is here because UML expands open to sys_open, not to a system
  * call instruction.
  */
@@ -90,3 +123,13 @@
 EXPORT_SYMBOL(kmap_atomic_to_page);
 #endif
 
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/kernel/main.c b/arch/um/kernel/main.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/kernel/main.c	2004-08-24 02:08:30 -07:00
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#include <asm/page.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "mem_user.h"
+#include "signal_user.h"
+#include "user.h"
+#include "init.h"
+#include "mode.h"
+#include "choose-mode.h"
+#include "uml-config.h"
+
+/* Set in set_stklim, which is called from main and __wrap_malloc.
+ * __wrap_malloc only calls it if main hasn't started.
+ */
+unsigned long stacksizelim;
+
+/* Set in main */
+char *linux_prog;
+
+#define PGD_BOUND (4 * 1024 * 1024)
+#define STACKSIZE (8 * 1024 * 1024)
+#define THREAD_NAME_LEN (256)
+
+static void set_stklim(void)
+{
+	struct rlimit lim;
+
+	if(getrlimit(RLIMIT_STACK, &lim) < 0){
+		perror("getrlimit");
+		exit(1);
+	}
+	if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){
+		lim.rlim_cur = STACKSIZE;
+		if(setrlimit(RLIMIT_STACK, &lim) < 0){
+			perror("setrlimit");
+			exit(1);
+		}
+	}
+	stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
+}
+
+static __init void do_uml_initcalls(void)
+{
+	initcall_t *call;
+
+	call = &__uml_initcall_start;
+	while (call < &__uml_initcall_end){;
+		(*call)();
+		call++;
+	}
+}
+
+static void last_ditch_exit(int sig)
+{
+	CHOOSE_MODE(kmalloc_ok = 0, (void) 0);
+	signal(SIGINT, SIG_DFL);
+	signal(SIGTERM, SIG_DFL);
+	signal(SIGHUP, SIG_DFL);
+	uml_cleanup();
+	exit(1);
+}
+
+extern int uml_exitcode;
+
+int main(int argc, char **argv, char **envp)
+{
+	char **new_argv;
+	sigset_t mask;
+	int ret, i;
+
+	/* Enable all signals except SIGIO - in some environments, we can
+	 * enter with some signals blocked
+	 */
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGIO);
+	if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
+		perror("sigprocmask");
+		exit(1);
+	}
+
+#ifdef UML_CONFIG_MODE_TT
+	/* Allocate memory for thread command lines */
+	if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
+
+		char padding[THREAD_NAME_LEN] = {
+			[ 0 ...  THREAD_NAME_LEN - 2] = ' ', '\0'
+		};
+
+		new_argv = malloc((argc + 2) * sizeof(char*));
+		if(!new_argv) {
+			perror("Allocating extended argv");
+			exit(1);
+		}
+
+		new_argv[0] = argv[0];
+		new_argv[1] = padding;
+
+		for(i = 2; i <= argc; i++)
+			new_argv[i] = argv[i - 1];
+		new_argv[argc + 1] = NULL;
+
+		execvp(new_argv[0], new_argv);
+		perror("execing with extended args");
+		exit(1);
+	}
+#endif
+
+	linux_prog = argv[0];
+
+	set_stklim();
+
+	new_argv = malloc((argc + 1) * sizeof(char *));
+	if(new_argv == NULL){
+		perror("Mallocing argv");
+		exit(1);
+	}
+	for(i=0;i<argc;i++){
+		new_argv[i] = strdup(argv[i]);
+		if(new_argv[i] == NULL){
+			perror("Mallocing an arg");
+			exit(1);
+		}
+	}
+	new_argv[argc] = NULL;
+
+	set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+	set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+	set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+
+	do_uml_initcalls();
+	ret = linux_main(argc, argv);
+
+	/* Reboot */
+	if(ret){
+		printf("\n");
+		execvp(new_argv[0], new_argv);
+		perror("Failed to exec kernel");
+		ret = 1;
+	}
+	printf("\n");
+	return(uml_exitcode);
+}
+
+#define CAN_KMALLOC() \
+	(kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1))
+
+extern void *__real_malloc(int);
+
+void *__wrap_malloc(int size)
+{
+	void *ret;
+
+	if(!CAN_KMALLOC())
+		return(__real_malloc(size));
+	else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
+		ret = um_kmalloc(size);
+	else ret = um_vmalloc(size);
+
+	/* glibc people insist that if malloc fails, errno should be
+	 * set by malloc as well. So we do.
+	 */
+	if(ret == NULL)
+		errno = ENOMEM;
+
+	return(ret);
+}
+
+void *__wrap_calloc(int n, int size)
+{
+	void *ptr = __wrap_malloc(n * size);
+
+	if(ptr == NULL) return(NULL);
+	memset(ptr, 0, n * size);
+	return(ptr);
+}
+
+extern void __real_free(void *);
+
+extern unsigned long high_physmem;
+
+void __wrap_free(void *ptr)
+{
+	unsigned long addr = (unsigned long) ptr;
+
+	/* We need to know how the allocation happened, so it can be correctly
+	 * freed.  This is done by seeing what region of memory the pointer is
+	 * in -
+	 * 	physical memory - kmalloc/kfree
+	 *	kernel virtual memory - vmalloc/vfree
+	 * 	anywhere else - malloc/free
+	 * If kmalloc is not yet possible, then the kernel memory regions
+	 * may not be set up yet, and the variables not initialized.  So,
+	 * free is called.
+	 */
+	if(CAN_KMALLOC()){
+		if((addr >= uml_physmem) && (addr <= high_physmem))
+			kfree(ptr);
+		else if((addr >= start_vm) && (addr <= end_vm))
+			vfree(ptr);
+		else
+			__real_free(ptr);
+	}
+	else __real_free(ptr);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
--- a/arch/um/kernel/mem.c	2004-06-24 01:55:57 -07:00
+++ b/arch/um/kernel/mem.c	2004-08-24 02:08:18 -07:00
@@ -1,74 +1,66 @@
 /* 
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
-#include "linux/config.h"
-#include "linux/module.h"
-#include "linux/types.h"
+#include "linux/stddef.h"
+#include "linux/kernel.h"
 #include "linux/mm.h"
-#include "linux/fs.h"
-#include "linux/init.h"
 #include "linux/bootmem.h"
 #include "linux/swap.h"
-#include "linux/slab.h"
-#include "linux/vmalloc.h"
 #include "linux/highmem.h"
+#include "linux/gfp.h"
 #include "asm/page.h"
-#include "asm/pgtable.h"
+#include "asm/fixmap.h"
 #include "asm/pgalloc.h"
-#include "asm/bitops.h"
-#include "asm/uaccess.h"
-#include "asm/tlb.h"
 #include "user_util.h"
 #include "kern_util.h"
-#include "mem_user.h"
-#include "mem.h"
 #include "kern.h"
-#include "init.h"
-#include "os.h"
-#include "mode_kern.h"
+#include "mem_user.h"
 #include "uml_uaccess.h"
+#include "os.h"
+
+extern char __binary_start;
 
 /* Changed during early boot */
-pgd_t swapper_pg_dir[1024];
-unsigned long high_physmem;
-unsigned long vm_start;
-unsigned long vm_end;
-unsigned long highmem;
 unsigned long *empty_zero_page = NULL;
 unsigned long *empty_bad_page = NULL;
-
-/* Not modified */
-const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
-
-extern char __init_begin, __init_end;
-extern long physmem_size;
-
-/* Not changed by UML */
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
-/* Changed during early boot */
+pgd_t swapper_pg_dir[1024];
+unsigned long highmem;
 int kmalloc_ok = 0;
 
-#define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1)
-struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL };
-#define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1)
-
-/* Changed during early boot */
 static unsigned long brk_end;
 
+void unmap_physmem(void)
+{
+	os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
+}
+
 static void map_cb(void *unused)
 {
 	map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
 }
 
-void unmap_physmem(void)
+#ifdef CONFIG_HIGHMEM
+static void setup_highmem(unsigned long highmem_start,
+			  unsigned long highmem_len)
 {
-	os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
-}
+	struct page *page;
+	unsigned long highmem_pfn;
+	int i;
 
-extern char __binary_start;
+	highmem_start_page = virt_to_page(highmem_start);
+
+	highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
+	for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
+		page = &mem_map[highmem_pfn + i];
+		ClearPageReserved(page);
+		set_bit(PG_highmem, &page->flags);
+		set_page_count(page, 1);
+		__free_page(page);
+	}
+}
+#endif
 
 void mem_init(void)
 {
@@ -103,50 +95,15 @@
 	totalhigh_pages = highmem >> PAGE_SHIFT;
 	totalram_pages += totalhigh_pages;
 	num_physpages = totalram_pages;
-	max_mapnr = totalram_pages;
 	max_pfn = totalram_pages;
 	printk(KERN_INFO "Memory: %luk available\n", 
 	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
 	kmalloc_ok = 1;
-}
-
-/* Changed during early boot */
-static unsigned long kmem_top = 0;
-
-unsigned long get_kmem_end(void)
-{
-	if(kmem_top == 0)
-		kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
-	return(kmem_top);
-}
-
-void set_kmem_end(unsigned long new)
-{
-	kmem_top = new;
-}
 
 #ifdef CONFIG_HIGHMEM
-/* Changed during early boot */
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
-
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
-#define kmap_get_fixmap_pte(vaddr)					\
-	pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-
-void __init kmap_init(void)
-{
-	unsigned long kmap_vstart;
-
-	/* cache the first kmap pte */
-	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
-	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
-	kmap_prot = PAGE_KERNEL;
+	setup_highmem(end_iomem, highmem);
+#endif
 }
-#endif /* CONFIG_HIGHMEM */
 
 static void __init fixrange_init(unsigned long start, unsigned long end, 
 				 pgd_t *pgd_base)
@@ -178,76 +135,24 @@
 	}
 }
 
-int init_maps(struct mem_region *region)
-{
-	struct page *p, *map;
-	int i, n, len;
-
-	if(region == &physmem_region){
-		region->mem_map = mem_map;
-		return(0);
-	}
-	else if(region->mem_map != NULL) return(0);
-
-	n = region->len >> PAGE_SHIFT;
-	len = n * sizeof(struct page);
-	if(kmalloc_ok){
-		map = kmalloc(len, GFP_KERNEL);
-		if(map == NULL) map = vmalloc(len);
-	}
-	else map = alloc_bootmem_low_pages(len);
-
-	if(map == NULL)
-		return(-ENOMEM);
-	for(i = 0; i < n; i++){
-		p = &map[i];
-		set_page_count(p, 0);
-		SetPageReserved(p);
-		INIT_LIST_HEAD(&p->list);
-	}
-	region->mem_map = map;
-	return(0);
-}
+#if CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
 
-DECLARE_MUTEX(regions_sem);
+#define kmap_get_fixmap_pte(vaddr)					\
+	pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
 
-static int setup_one_range(int fd, char *driver, unsigned long start, 
-			   unsigned long pfn, int len, 
-			   struct mem_region *region)
+void __init kmap_init(void)
 {
-	int i;
-
-	down(&regions_sem);
-	for(i = 0; i < NREGIONS; i++){
-		if(regions[i] == NULL) break;		
-	}
-	if(i == NREGIONS){
-		printk("setup_range : no free regions\n");
-		i = -1;
-		goto out;
-	}
-
-	if(fd == -1)
-		fd = create_mem_file(len);
+	unsigned long kmap_vstart;
 
-	if(region == NULL){
-		region = alloc_bootmem_low_pages(sizeof(*region));
-		if(region == NULL)
-			panic("Failed to allocating mem_region");
-	}
+	/* cache the first kmap pte */
+	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
 
-	*region = ((struct mem_region) { .driver 	= driver,
-					 .start_pfn 	= pfn,
-					 .start 	= start, 
-					 .len 		= len, 
-					 .fd 		= fd } );
-	regions[i] = region;
- out:
-	up(&regions_sem);
-	return(i);
+	kmap_prot = PAGE_KERNEL;
 }
 
-#ifdef CONFIG_HIGHMEM
 static void init_highmem(void)
 {
 	pgd_t *pgd;
@@ -268,63 +173,20 @@
 
 	kmap_init();
 }
-
-void setup_highmem(unsigned long len)
-{
-	struct mem_region *region;
-	struct page *page, *map;
-	unsigned long phys;
-	int i, cur, index;
-
-	phys = physmem_size;
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		i = setup_one_range(-1, NULL, -1, phys >> PAGE_SHIFT, cur, 
-				    NULL);
-		if(i == -1){
-			printk("setup_highmem - setup_one_range failed\n");
-			return;
-		}
-		region = regions[i];
-		index = phys / PAGE_SIZE;
-		region->mem_map = &mem_map[index];
-
-		map = region->mem_map;
-		for(i = 0; i < (cur >> PAGE_SHIFT); i++){
-			page = &map[i];
-			ClearPageReserved(page);
-			set_bit(PG_highmem, &page->flags);
-			set_page_count(page, 1);
-			__free_page(page);
-		}
-		phys += cur;
-		len -= cur;
-	} while(len > 0);
-}
-#endif
+#endif /* CONFIG_HIGHMEM */
 
 void paging_init(void)
 {
-	struct mem_region *region;
-	unsigned long zones_size[MAX_NR_ZONES], start, end, vaddr;
-	int i, index;
+	unsigned long zones_size[MAX_NR_ZONES], vaddr;
+	int i;
 
 	empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
 	empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
 	for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) 
 		zones_size[i] = 0;
-	zones_size[0] = (high_physmem >> PAGE_SHIFT) - 
-		(uml_physmem >> PAGE_SHIFT);
+	zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
 	zones_size[2] = highmem >> PAGE_SHIFT;
 	free_area_init(zones_size);
-	start = phys_region_index(__pa(uml_physmem));
-	end = phys_region_index(__pa(high_physmem - 1));
-	for(i = start; i <= end; i++){
-		region = regions[i];
-		index = (region->start - uml_physmem) / PAGE_SIZE;
-		region->mem_map = &mem_map[index];
-		if(i > start) free_bootmem(__pa(region->start), region->len);
-	}
 
 	/*
 	 * Fixed mappings, only the page table structure has to be
@@ -335,15 +197,33 @@
 
 #ifdef CONFIG_HIGHMEM
 	init_highmem();
-	setup_highmem(highmem);
 #endif
 }
 
-pte_t __bad_page(void)
+struct page *arch_validate(struct page *page, int mask, int order)
 {
-	clear_page(empty_bad_page);
-        return pte_mkdirty(mk_pte((struct page *) empty_bad_page, 
-				  PAGE_SHARED));
+	unsigned long addr, zero = 0;
+	int i;
+
+ again:
+	if(page == NULL) return(page);
+	if(PageHighMem(page)) return(page);
+
+	addr = (unsigned long) page_address(page);
+	for(i = 0; i < (1 << order); i++){
+		current->thread.fault_addr = (void *) addr;
+		if(__do_copy_to_user((void *) addr, &zero,
+				     sizeof(zero),
+				     &current->thread.fault_addr,
+				     &current->thread.fault_catcher)){
+			if(!(mask & __GFP_WAIT)) return(NULL);
+			else break;
+		}
+		addr += PAGE_SIZE;
+	}
+	if(i == (1 << order)) return(page);
+	page = alloc_pages(mask, order);
+	goto again;
 }
 
 /* This can't do anything because nothing in the kernel image can be freed
@@ -400,395 +280,6 @@
         printk("%d pages shared\n", shared);
         printk("%d pages swap cached\n", cached);
 }
-
-static int __init uml_mem_setup(char *line, int *add)
-{
-	char *retptr;
-	physmem_size = memparse(line,&retptr);
-	return 0;
-}
-__uml_setup("mem=", uml_mem_setup,
-"mem=<Amount of desired ram>\n"
-"    This controls how much \"physical\" memory the kernel allocates\n"
-"    for the system. The size is specified as a number followed by\n"
-"    one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
-"    This is not related to the amount of memory in the physical\n"
-"    machine. It can be more, and the excess, if it's ever used, will\n"
-"    just be swapped out.\n        Example: mem=64M\n\n"
-);
-
-struct page *arch_validate(struct page *page, int mask, int order)
-{
-	unsigned long addr, zero = 0;
-	int i;
-
- again:
-	if(page == NULL) return(page);
-	if(PageHighMem(page)) return(page);
-
-	addr = (unsigned long) page_address(page);
-	for(i = 0; i < (1 << order); i++){
-		current->thread.fault_addr = (void *) addr;
-		if(__do_copy_to_user((void *) addr, &zero, 
-				     sizeof(zero),
-				     &current->thread.fault_addr,
-				     &current->thread.fault_catcher)){
-			if(!(mask & __GFP_WAIT)) return(NULL);
-			else break;
-		}
-		addr += PAGE_SIZE;
-	}
-	if(i == (1 << order)) return(page);
-	page = alloc_pages(mask, order);
-	goto again;
-}
-
-DECLARE_MUTEX(vm_reserved_sem);
-static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved);
-
-/* Static structures, linked in to the list in early boot */
-static struct vm_reserved head = {
-	.list 		= LIST_HEAD_INIT(head.list),
-	.start 		= 0,
-	.end 		= 0xffffffff
-};
-
-static struct vm_reserved tail = {
-	.list 		= LIST_HEAD_INIT(tail.list),
-	.start 		= 0,
-	.end 		= 0xffffffff
-};
-
-void set_usable_vm(unsigned long start, unsigned long end)
-{
-	list_add(&head.list, &vm_reserved);
-	list_add(&tail.list, &head.list);
-	head.end = start;
-	tail.start = end;
-}
-
-int reserve_vm(unsigned long start, unsigned long end, void *e)
-	       
-{
-	struct vm_reserved *entry = e, *reserved, *prev;
-	struct list_head *ele;
-	int err;
-
-	down(&vm_reserved_sem);
-	list_for_each(ele, &vm_reserved){
-		reserved = list_entry(ele, struct vm_reserved, list);
-		if(reserved->start >= end) goto found;
-	}
-	panic("Reserved vm out of range");
- found:
-	prev = list_entry(ele->prev, struct vm_reserved, list);
-	if(prev->end > start)
-		panic("Can't reserve vm");
-	if(entry == NULL)
-		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-	if(entry == NULL){
-		printk("reserve_vm : Failed to allocate entry\n");
-		err = -ENOMEM;
-		goto out;
-	}
-	*entry = ((struct vm_reserved) 
-		{ .list 	= LIST_HEAD_INIT(entry->list),
-		  .start 	= start,
-		  .end 		= end });
-	list_add(&entry->list, &prev->list);
-	err = 0;
- out:
-	up(&vm_reserved_sem);
-	return(0);
-}
-
-unsigned long get_vm(unsigned long len)
-{
-	struct vm_reserved *this, *next;
-	struct list_head *ele;
-	unsigned long start;
-	int err;
-	
-	down(&vm_reserved_sem);
-	list_for_each(ele, &vm_reserved){
-		this = list_entry(ele, struct vm_reserved, list);
-		next = list_entry(ele->next, struct vm_reserved, list);
-		if((this->start < next->start) && 
-		   (this->end + len + PAGE_SIZE <= next->start))
-			goto found;
-	}
-	up(&vm_reserved_sem);
-	return(0);
- found:
-	up(&vm_reserved_sem);
-	start = (unsigned long) UML_ROUND_UP(this->end) + PAGE_SIZE;
-	err = reserve_vm(start, start + len, NULL);
-	if(err) return(0);
-	return(start);
-}
-
-int nregions(void)
-{
-	return(NREGIONS);
-}
-
-void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn,
-		 unsigned long len, int need_vm, struct mem_region *region, 
-		 void *reserved)
-{
-	int i, cur;
-
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		i = setup_one_range(fd, driver, start, pfn, cur, region);
-		region = regions[i];
-		if(need_vm && setup_region(region, reserved)){
-			kfree(region);
-			regions[i] = NULL;
-			return;
-		}
-		start += cur;
-		if(pfn != -1) pfn += cur;
-		len -= cur;
-	} while(len > 0);
-}
-
-struct iomem {
-	char *name;
-	int fd;
-	unsigned long size;
-};
-
-/* iomem regions can only be added on the command line at the moment.  
- * Locking will be needed when they can be added via mconsole.
- */
-
-struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] =
-					 { .name  	= NULL,
-					   .fd  	= -1,
-					   .size 	= 0 } };
-
-int num_iomem_regions = 0;
-
-void add_iomem(char *name, int fd, unsigned long size)
-{
-	if(num_iomem_regions == sizeof(iomem_regions)/sizeof(iomem_regions[0]))
-		return;
-	size = (size + PAGE_SIZE - 1) & PAGE_MASK;
-	iomem_regions[num_iomem_regions++] = 
-		((struct iomem) { .name 	= name,
-				  .fd 		= fd,
-				  .size 	= size } );
-}
-
-int setup_iomem(void)
-{
-	struct iomem *iomem;
-	int i;
-
-	for(i = 0; i < num_iomem_regions; i++){
-		iomem = &iomem_regions[i];
-		setup_range(iomem->fd, iomem->name, -1, -1, iomem->size, 1, 
-			    NULL, NULL);
-	}
-	return(0);
-}
-
-__initcall(setup_iomem);
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-
-/* Changed during early boot */
-static struct mem_region physmem_region;
-static struct vm_reserved physmem_reserved;
-
-void setup_physmem(unsigned long start, unsigned long reserve_end,
-		   unsigned long len)
-{
-	struct mem_region *region = &physmem_region;
-	struct vm_reserved *reserved = &physmem_reserved;
-	unsigned long cur, pfn = 0;
-	int do_free = 1, bootmap_size;
-
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		if(region == NULL) 
-			region = alloc_bootmem_low_pages(sizeof(*region));
-		if(reserved == NULL) 
-			reserved = alloc_bootmem_low_pages(sizeof(*reserved));
-		if((region == NULL) || (reserved == NULL))
-			panic("Couldn't allocate physmem region or vm "
-			      "reservation\n");
-		setup_range(-1, NULL, start, pfn, cur, 1, region, reserved);
-
-		if(do_free){
-			unsigned long reserve = reserve_end - start;
-			int pfn = PFN_UP(__pa(reserve_end));
-			int delta = (len - reserve) >> PAGE_SHIFT;
-
-			bootmap_size = init_bootmem(pfn, pfn + delta);
-			free_bootmem(__pa(reserve_end) + bootmap_size,
-				     cur - bootmap_size - reserve);
-			do_free = 0;
-		}
-		start += cur;
-		pfn += cur >> PAGE_SHIFT;
-		len -= cur;
-		region = NULL;
-		reserved = NULL;
-	} while(len > 0);
-}
-
-struct mem_region *phys_region(unsigned long phys)
-{
-	unsigned int n = phys_region_index(phys);
-
-	if(regions[n] == NULL) 
-		panic("Physical address in uninitialized region");
-	return(regions[n]);
-}
-
-unsigned long phys_offset(unsigned long phys)
-{
-	return(phys_addr(phys));
-}
-
-struct page *phys_mem_map(unsigned long phys)
-{
-	return((struct page *) phys_region(phys)->mem_map);
-}
-
-struct page *pte_mem_map(pte_t pte)
-{
-	return(phys_mem_map(pte_val(pte)));
-}
-
-struct mem_region *page_region(struct page *page, int *index_out)
-{
-	int i;
-	struct mem_region *region;
-	struct page *map;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		map = region->mem_map;
-		if((page >= map) && (page < &map[region->len >> PAGE_SHIFT])){
-			if(index_out != NULL) *index_out = i;
-			return(region);
-		}
-	}
-	panic("No region found for page");
-	return(NULL);
-}
-
-unsigned long page_to_pfn(struct page *page)
-{
-	struct mem_region *region = page_region(page, NULL);
-
-	return(region->start_pfn + (page - (struct page *) region->mem_map));
-}
-
-struct mem_region *pfn_to_region(unsigned long pfn, int *index_out)
-{
-	struct mem_region *region;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL)
-			continue;
-
-		if((region->start_pfn <= pfn) &&
-		   (region->start_pfn + (region->len >> PAGE_SHIFT) > pfn)){
-			if(index_out != NULL) 
-				*index_out = i;
-			return(region);
-		}
-	}
-	return(NULL);
-}
-
-struct page *pfn_to_page(unsigned long pfn)
-{
-	struct mem_region *region = pfn_to_region(pfn, NULL);
-	struct page *mem_map = (struct page *) region->mem_map;
-
-	return(&mem_map[pfn - region->start_pfn]);
-}
-
-unsigned long phys_to_pfn(unsigned long p)
-{
-	struct mem_region *region = regions[phys_region_index(p)];
-
-	return(region->start_pfn + (phys_addr(p) >> PAGE_SHIFT));
-}
-
-unsigned long pfn_to_phys(unsigned long pfn)
-{
-	int n;
-	struct mem_region *region = pfn_to_region(pfn, &n);
-
-	return(mk_phys((pfn - region->start_pfn) << PAGE_SHIFT, n));
-}
-
-struct page *page_mem_map(struct page *page)
-{
-	return((struct page *) page_region(page, NULL)->mem_map);
-}
-
-extern unsigned long region_pa(void *virt)
-{
-	struct mem_region *region;
-	unsigned long addr = (unsigned long) virt;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		if((region->start <= addr) && 
-		   (addr <= region->start + region->len))
-			return(mk_phys(addr - region->start, i));
-	}
-	panic("region_pa : no region for virtual address");
-	return(0);
-}
-
-extern void *region_va(unsigned long phys)
-{
-	return((void *) (phys_region(phys)->start + phys_addr(phys)));
-}
-
-unsigned long page_to_phys(struct page *page)
-{
-	int n;
-	struct mem_region *region = page_region(page, &n);
-	struct page *map = region->mem_map;
-	return(mk_phys((page - map) << PAGE_SHIFT, n));
-}
-
-struct page *phys_to_page(unsigned long phys)
-{
-	struct page *mem_map;
-
-	mem_map = phys_mem_map(phys);
-	return(mem_map + (phys_offset(phys) >> PAGE_SHIFT));
-}
-
-static int setup_mem_maps(void)
-{
-	struct mem_region *region;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if((region != NULL) && (region->fd > 0)) init_maps(region);
-	}
-	return(0);
-}
-
-__initcall(setup_mem_maps);
 
 /*
  * Allocate and free page tables.
diff -Nru a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c
--- a/arch/um/kernel/mem_user.c	2002-11-20 20:04:11 -08:00
+++ b/arch/um/kernel/mem_user.c	2004-08-24 02:08:18 -07:00
@@ -34,10 +34,9 @@
 #include <stddef.h>
 #include <stdarg.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
-#include <sys/stat.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 #include "kern_util.h"
@@ -47,105 +46,145 @@
 #include "init.h"
 #include "os.h"
 #include "tempfile.h"
+#include "kern_constants.h"
 
 extern struct mem_region physmem_region;
 
 #define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
 
-int create_mem_file(unsigned long len)
+static int create_tmp_file(unsigned long len)
 {
-	int fd;
+	int fd, err;
 	char zero;
 
 	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
-	if (fchmod(fd, 0777) < 0){
-		perror("fchmod");
+	if(fd < 0) {
+		os_print_error(fd, "make_tempfile");
+		exit(1);
+	}
+
+	err = os_mode_fd(fd, 0777);
+	if(err < 0){
+		os_print_error(err, "os_mode_fd");
 		exit(1);
 	}
-	if(os_seek_file(fd, len) < 0){
-		perror("lseek");
+	err = os_seek_file(fd, len);
+	if(err < 0){
+		os_print_error(err, "os_seek_file");
 		exit(1);
 	}
 	zero = 0;
-	if(write(fd, &zero, 1) != 1){
-		perror("write");
+	err = os_write_file(fd, &zero, 1);
+	if(err != 1){
+		os_print_error(err, "os_write_file");
 		exit(1);
 	}
-	if(fcntl(fd, F_SETFD, 1) != 0)
-		perror("Setting FD_CLOEXEC failed");
+
 	return(fd);
 }
 
-int setup_region(struct mem_region *region, void *entry)
+static int have_devanon = 0;
+
+void check_devanon(void)
+{
+	int fd;
+
+	printk("Checking for /dev/anon on the host...");
+	fd = open("/dev/anon", O_RDWR);
+	if(fd < 0){
+		printk("Not available (open failed with errno %d)\n", errno);
+		return;
+	}
+
+	printk("OK\n");
+	have_devanon = 1;
+}
+
+static int create_anon_file(unsigned long len)
 {
-	void *loc, *start;
-	char *driver;
-	int err, offset;
-
-	if(region->start != -1){
-		err = reserve_vm(region->start, 
-				 region->start + region->len, entry);
-		if(err){
-			printk("setup_region : failed to reserve "
-			       "0x%x - 0x%x for driver '%s'\n",
-			       region->start, 
-			       region->start + region->len,
-			       region->driver);
-			return(-1);
-		}
-	}
-	else region->start = get_vm(region->len);
-	if(region->start == 0){
-		if(region->driver == NULL) driver = "physmem";
-		else driver = region->driver;
-		printk("setup_region : failed to find vm for "
-		       "driver '%s' (length %d)\n", driver, region->len);
-		return(-1);
-	}
-	if(region->start == uml_physmem){
-		start = (void *) uml_reserved;
-		offset = uml_reserved - uml_physmem;
-	}
-	else {
-		start = (void *) region->start;
-		offset = 0;
-	}
-
-	loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE, 
-		   MAP_SHARED | MAP_FIXED, region->fd, offset);
-	if(loc != start){
-		perror("Mapping memory");
+	void *addr;
+	int fd;
+
+	fd = open("/dev/anon", O_RDWR);
+	if(fd < 0) {
+		os_print_error(fd, "opening /dev/anon");
 		exit(1);
 	}
-	return(0);
+
+	addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0);
+	if(addr == MAP_FAILED){
+		os_print_error((int) addr, "mapping physmem file");
+		exit(1);
+	}
+	munmap(addr, len);
+
+	return(fd);
+}
+
+int create_mem_file(unsigned long len)
+{
+	int err, fd;
+
+	if(have_devanon)
+		fd = create_anon_file(len);
+	else fd = create_tmp_file(len);
+
+	err = os_set_exec_close(fd, 1);
+	if(err < 0)
+		os_print_error(err, "exec_close");
+	return(fd);
 }
 
+struct iomem_region *iomem_regions = NULL;
+int iomem_size = 0;
+
 static int __init parse_iomem(char *str, int *add)
 {
-	struct stat buf;
+	struct iomem_region *new;
+	struct uml_stat buf;
 	char *file, *driver;
-	int fd;
+	int fd, err;
 
 	driver = str;
 	file = strchr(str,',');
 	if(file == NULL){
-		printk("parse_iomem : failed to parse iomem\n");
-		return(1);
+		printf("parse_iomem : failed to parse iomem\n");
+		goto out;
 	}
 	*file = '\0';
 	file++;
 	fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("parse_iomem - Couldn't open io file, errno = %d\n", 
-		       errno);
-		return(1);
-	}
-	if(fstat(fd, &buf) < 0) {
-		printk("parse_iomem - cannot fstat file, errno = %d\n", errno);
-		return(1);
+		os_print_error(fd, "parse_iomem - Couldn't open io file");
+		goto out;
 	}
-	add_iomem(driver, fd, buf.st_size);
+
+	err = os_stat_fd(fd, &buf);
+	if(err < 0){
+		os_print_error(err, "parse_iomem - cannot stat_fd file");
+		goto out_close;
+	}
+
+	new = malloc(sizeof(*new));
+	if(new == NULL){
+		perror("Couldn't allocate iomem_region struct");
+		goto out_close;
+	}
+
+	*new = ((struct iomem_region) { .next		= iomem_regions,
+					.driver		= driver,
+					.fd		= fd,
+					.size		= buf.ust_size,
+					.phys		= 0,
+					.virt		= 0 });
+	iomem_regions = new;
+	iomem_size += new->size + UM_KERN_PAGE_SIZE;
+
 	return(0);
+ out_close:
+	os_close_file(fd);
+ out:
+	return(1);
 }
 
 __uml_setup("iomem=", parse_iomem,
@@ -153,71 +192,18 @@
 "    Configure <file> as an IO memory region named <name>.\n\n"
 );
 
-#ifdef notdef
-int logging = 0;
-int logging_fd = -1;
-
-int logging_line = 0;
-char logging_buf[256];
-
-void log(char *fmt, ...)
-{
-	va_list ap;
-	struct timeval tv;
-	struct openflags flags;
-
-	if(logging == 0) return;
-	if(logging_fd < 0){
-		flags = of_create(of_trunc(of_rdrw(OPENFLAGS())));
-		logging_fd = os_open_file("log", flags, 0644);
-	}
-	gettimeofday(&tv, NULL);
-	sprintf(logging_buf, "%d\t %u.%u  ", logging_line++, tv.tv_sec, 
-		tv.tv_usec);
-	va_start(ap, fmt);
-	vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
-	va_end(ap);
-	write(logging_fd, logging_buf, strlen(logging_buf));
-}
-#endif
-
-int map_memory(unsigned long virt, unsigned long phys, unsigned long len, 
-	       int r, int w, int x)
-{
-	struct mem_region *region = phys_region(phys);
-
-	return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len,
-			     r, w, x));
-}
-
 int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
 		   int must_succeed)
 {
-	if(os_protect_memory((void *) addr, len, r, w, x) < 0){
+	int err;
+
+	err = os_protect_memory((void *) addr, len, r, w, x);
+	if(err < 0){
                 if(must_succeed)
-                        panic("protect failed, errno = %d", errno);
-                else return(-errno);
+			panic("protect failed, err = %d", -err);
+		else return(err);
 	}
 	return(0);
-}
-
-unsigned long find_iomem(char *driver, unsigned long *len_out)
-{
-	struct mem_region *region;
-	int i, n;
-
-	n = nregions();
-	for(i = 0; i < n; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		if((region->driver != NULL) &&
-		   !strcmp(region->driver, driver)){
-			*len_out = region->len;
-			return(region->start);
-		}
-	}
-	*len_out = 0;
-	return 0;
 }
 
 /*
diff -Nru a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/kernel/physmem.c	2004-08-24 11:13:14 -07:00
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/mm.h"
+#include "linux/ghash.h"
+#include "linux/slab.h"
+#include "linux/vmalloc.h"
+#include "linux/bootmem.h"
+#include "asm/types.h"
+#include "asm/pgtable.h"
+#include "kern_util.h"
+#include "user_util.h"
+#include "mode_kern.h"
+#include "mem.h"
+#include "mem_user.h"
+#include "os.h"
+#include "kern.h"
+#include "init.h"
+
+#if 0
+static pgd_t physmem_pgd[PTRS_PER_PGD];
+
+static struct phys_desc *lookup_mapping(void *addr)
+{
+	pgd = &physmem_pgd[pgd_index(addr)];
+	if(pgd_none(pgd))
+		return(NULL);
+
+	pmd = pmd_offset(pgd, addr);
+	if(pmd_none(pmd))
+		return(NULL);
+
+	pte = pte_offset_kernel(pmd, addr);
+	return((struct phys_desc *) pte_val(pte));
+}
+
+static struct add_mapping(void *addr, struct phys_desc *new)
+{
+}
+#endif
+
+#define PHYS_HASHSIZE (8192)
+
+struct phys_desc;
+
+DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc);
+
+struct phys_desc {
+	struct virtmem_ptrs virt_ptrs;
+	int fd;
+	__u64 offset;
+	void *virt;
+	unsigned long phys;
+	struct list_head list;
+};
+
+struct virtmem_table virtmem_hash;
+
+static int virt_cmp(void *virt1, void *virt2)
+{
+	return(virt1 != virt2);
+}
+
+static int virt_hash(void *virt)
+{
+	unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT;
+	return(addr % PHYS_HASHSIZE);
+}
+
+DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp,
+	 virt_hash);
+
+LIST_HEAD(descriptor_mappings);
+
+struct desc_mapping {
+	int fd;
+	struct list_head list;
+	struct list_head pages;
+};
+
+static struct desc_mapping *find_mapping(int fd)
+{
+	struct desc_mapping *desc;
+	struct list_head *ele;
+
+	list_for_each(ele, &descriptor_mappings){
+		desc = list_entry(ele, struct desc_mapping, list);
+		if(desc->fd == fd)
+			return(desc);
+	}
+
+	return(NULL);
+}
+
+static struct desc_mapping *descriptor_mapping(int fd)
+{
+	struct desc_mapping *desc;
+
+	desc = find_mapping(fd);
+	if(desc != NULL)
+		return(desc);
+
+	desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
+	if(desc == NULL)
+		return(NULL);
+
+	*desc = ((struct desc_mapping)
+		{ .fd =		fd,
+		  .list =	LIST_HEAD_INIT(desc->list),
+		  .pages =	LIST_HEAD_INIT(desc->pages) });
+	list_add(&desc->list, &descriptor_mappings);
+
+	return(desc);
+}
+
+int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
+{
+	struct desc_mapping *fd_maps;
+	struct phys_desc *desc;
+	unsigned long phys;
+	int err;
+
+	fd_maps = descriptor_mapping(fd);
+	if(fd_maps == NULL)
+		return(-ENOMEM);
+
+	phys = __pa(virt);
+	if(find_virtmem_hash(&virtmem_hash, virt) != NULL)
+		panic("Address 0x%p is already substituted\n", virt);
+
+	err = -ENOMEM;
+	desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
+	if(desc == NULL)
+		goto out;
+
+	*desc = ((struct phys_desc)
+		{ .virt_ptrs =	{ NULL, NULL },
+		  .fd =		fd,
+		  .offset =		offset,
+		  .virt =		virt,
+		  .phys =		__pa(virt),
+		  .list = 		LIST_HEAD_INIT(desc->list) });
+	insert_virtmem_hash(&virtmem_hash, desc);
+
+	list_add(&desc->list, &fd_maps->pages);
+
+	virt = (void *) ((unsigned long) virt & PAGE_MASK);
+	err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0);
+	if(!err)
+		goto out;
+
+	remove_virtmem_hash(&virtmem_hash, desc);
+	kfree(desc);
+ out:
+	return(err);
+}
+
+static int physmem_fd = -1;
+
+static void remove_mapping(struct phys_desc *desc)
+{
+	void *virt = desc->virt;
+	int err;
+
+	remove_virtmem_hash(&virtmem_hash, desc);
+	list_del(&desc->list);
+	kfree(desc);
+
+	err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0);
+	if(err)
+		panic("Failed to unmap block device page from physical memory, "
+		      "errno = %d", -err);
+}
+
+int physmem_remove_mapping(void *virt)
+{
+	struct phys_desc *desc;
+
+	virt = (void *) ((unsigned long) virt & PAGE_MASK);
+	desc = find_virtmem_hash(&virtmem_hash, virt);
+	if(desc == NULL)
+		return(0);
+
+	remove_mapping(desc);
+	return(1);
+}
+
+void physmem_forget_descriptor(int fd)
+{
+	struct desc_mapping *desc;
+	struct phys_desc *page;
+	struct list_head *ele, *next;
+	__u64 offset;
+	void *addr;
+	int err;
+
+	desc = find_mapping(fd);
+	if(desc == NULL)
+		return;
+
+	list_for_each_safe(ele, next, &desc->pages){
+		page = list_entry(ele, struct phys_desc, list);
+		offset = page->offset;
+		addr = page->virt;
+		remove_mapping(page);
+		err = os_seek_file(fd, offset);
+		if(err)
+			panic("physmem_forget_descriptor - failed to seek "
+			      "to %lld in fd %d, error = %d\n",
+			      offset, fd, -err);
+		err = os_read_file(fd, addr, PAGE_SIZE);
+		if(err < 0)
+			panic("physmem_forget_descriptor - failed to read "
+			      "from fd %d to 0x%p, error = %d\n",
+			      fd, addr, -err);
+	}
+
+	list_del(&desc->list);
+	kfree(desc);
+}
+
+void arch_free_page(struct page *page, int order)
+{
+	void *virt;
+	int i;
+
+	for(i = 0; i < (1 << order); i++){
+		virt = __va(page_to_phys(page + i));
+		physmem_remove_mapping(virt);
+	}
+}
+
+int is_remapped(void *virt)
+{
+	return(find_virtmem_hash(&virtmem_hash, virt) != NULL);
+}
+
+/* Changed during early boot */
+unsigned long high_physmem;
+
+extern unsigned long physmem_size;
+
+void *to_virt(unsigned long phys)
+{
+	return((void *) uml_physmem + phys);
+}
+
+unsigned long to_phys(void *virt)
+{
+	return(((unsigned long) virt) - uml_physmem);
+}
+
+int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
+{
+	struct page *p, *map;
+	unsigned long phys_len, phys_pages, highmem_len, highmem_pages;
+	unsigned long iomem_len, iomem_pages, total_len, total_pages;
+	int i;
+
+	phys_pages = physmem >> PAGE_SHIFT;
+	phys_len = phys_pages * sizeof(struct page);
+
+	iomem_pages = iomem >> PAGE_SHIFT;
+	iomem_len = iomem_pages * sizeof(struct page);
+
+	highmem_pages = highmem >> PAGE_SHIFT;
+	highmem_len = highmem_pages * sizeof(struct page);
+
+	total_pages = phys_pages + iomem_pages + highmem_pages;
+	total_len = phys_len + iomem_pages + highmem_len;
+
+	if(kmalloc_ok){
+		map = kmalloc(total_len, GFP_KERNEL);
+		if(map == NULL)
+			map = vmalloc(total_len);
+	}
+	else map = alloc_bootmem_low_pages(total_len);
+
+	if(map == NULL)
+		return(-ENOMEM);
+
+	for(i = 0; i < total_pages; i++){
+		p = &map[i];
+		set_page_count(p, 0);
+		SetPageReserved(p);
+		INIT_LIST_HEAD(&p->lru);
+	}
+
+	mem_map = map;
+	max_mapnr = total_pages;
+	return(0);
+}
+
+struct page *phys_to_page(const unsigned long phys)
+{
+	return(&mem_map[phys >> PAGE_SHIFT]);
+}
+
+struct page *__virt_to_page(const unsigned long virt)
+{
+	return(&mem_map[__pa(virt) >> PAGE_SHIFT]);
+}
+
+unsigned long page_to_phys(struct page *page)
+{
+	return((page - mem_map) << PAGE_SHIFT);
+}
+
+pte_t mk_pte(struct page *page, pgprot_t pgprot)
+{
+	pte_t pte;
+
+	pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot);
+	if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte));
+	return(pte);
+}
+
+/* Changed during early boot */
+static unsigned long kmem_top = 0;
+
+unsigned long get_kmem_end(void)
+{
+	if(kmem_top == 0)
+		kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
+	return(kmem_top);
+}
+
+void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
+		int r, int w, int x)
+{
+	__u64 offset;
+	int fd, err;
+
+	fd = phys_mapping(phys, &offset);
+	err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
+	if(err)
+		panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
+		      "err = %d\n", virt, fd, offset, len, r, w, x, err);
+}
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+
+void setup_physmem(unsigned long start, unsigned long reserve_end,
+		   unsigned long len, unsigned long highmem)
+{
+	unsigned long reserve = reserve_end - start;
+	int pfn = PFN_UP(__pa(reserve_end));
+	int delta = (len - reserve) >> PAGE_SHIFT;
+	int err, offset, bootmap_size;
+
+	physmem_fd = create_mem_file(len + highmem);
+
+	offset = uml_reserved - uml_physmem;
+	err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
+			    len - offset, 1, 1, 0);
+	if(err < 0){
+		os_print_error(err, "Mapping memory");
+		exit(1);
+	}
+
+	bootmap_size = init_bootmem(pfn, pfn + delta);
+	free_bootmem(__pa(reserve_end) + bootmap_size,
+		     len - bootmap_size - reserve);
+}
+
+int phys_mapping(unsigned long phys, __u64 *offset_out)
+{
+	struct phys_desc *desc = find_virtmem_hash(&virtmem_hash,
+						   __va(phys & PAGE_MASK));
+	int fd = -1;
+
+	if(desc != NULL){
+		fd = desc->fd;
+		*offset_out = desc->offset;
+	}
+	else if(phys < physmem_size){
+		fd = physmem_fd;
+		*offset_out = phys;
+	}
+	else if(phys < __pa(end_iomem)){
+		struct iomem_region *region = iomem_regions;
+
+		while(region != NULL){
+			if((phys >= region->phys) &&
+			   (phys < region->phys + region->size)){
+				fd = region->fd;
+				*offset_out = phys - region->phys;
+				break;
+			}
+			region = region->next;
+		}
+	}
+	else if(phys < __pa(end_iomem) + highmem){
+		fd = physmem_fd;
+		*offset_out = phys - iomem_size;
+	}
+
+	return(fd);
+}
+
+static int __init uml_mem_setup(char *line, int *add)
+{
+	char *retptr;
+	physmem_size = memparse(line,&retptr);
+	return 0;
+}
+__uml_setup("mem=", uml_mem_setup,
+"mem=<Amount of desired ram>\n"
+"    This controls how much \"physical\" memory the kernel allocates\n"
+"    for the system. The size is specified as a number followed by\n"
+"    one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
+"    This is not related to the amount of memory in the host.  It can\n"
+"    be more, and the excess, if it's ever used, will just be swapped out.\n"
+"	Example: mem=64M\n\n"
+);
+
+unsigned long find_iomem(char *driver, unsigned long *len_out)
+{
+	struct iomem_region *region = iomem_regions;
+
+	while(region != NULL){
+		if(!strcmp(region->driver, driver)){
+			*len_out = region->size;
+			return(region->virt);
+		}
+	}
+
+	return(0);
+}
+
+int setup_iomem(void)
+{
+	struct iomem_region *region = iomem_regions;
+	unsigned long iomem_start = high_physmem + PAGE_SIZE;
+	int err;
+
+	while(region != NULL){
+		err = os_map_memory((void *) iomem_start, region->fd, 0,
+				    region->size, 1, 1, 0);
+		if(err)
+			printk("Mapping iomem region for driver '%s' failed, "
+			       "errno = %d\n", region->driver, -err);
+		else {
+			region->virt = iomem_start;
+			region->phys = __pa(region->virt);
+		}
+
+		iomem_start += region->size + PAGE_SIZE;
+		region = region->next;
+	}
+
+	return(0);
+}
+
+__initcall(setup_iomem);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/kernel/process.c b/arch/um/kernel/process.c
--- a/arch/um/kernel/process.c	2003-02-05 20:15:10 -08:00
+++ b/arch/um/kernel/process.c	2004-08-24 02:08:29 -07:00
@@ -9,18 +9,17 @@
 #include <sched.h>
 #include <errno.h>
 #include <stdarg.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <setjmp.h>
 #include <sys/time.h>
 #include <sys/ptrace.h>
-#include <sys/ioctl.h>
 #include <sys/wait.h>
 #include <sys/mman.h>
 #include <asm/ptrace.h>
 #include <asm/sigcontext.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
+#include <asm/user.h>
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
@@ -58,7 +57,11 @@
 {
 	int flags = altstack ? SA_ONSTACK : 0;
 
-	set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+	/* NODEFER is set here because SEGV isn't turned back on when the
+	 * handler is ready to receive signals.  This causes any segfault
+	 * during a copy_user to kill the process because the fault is blocked.
+	 */
+	set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags | SA_NODEFER,
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, 
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
@@ -72,7 +75,6 @@
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGUSR2, (__sighandler_t) sig_handler, 
 		    SA_NOMASK | flags, -1);
-	(void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0);
 	signal(SIGHUP, SIG_IGN);
 
 	init_irq_signals(altstack);
@@ -122,12 +124,17 @@
 
 	/* Start the process and wait for it to kill itself */
 	new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg);
-	if(new_pid < 0) return(-errno);
-	while((err = waitpid(new_pid, &status, 0) < 0) && (errno == EINTR)) ;
-	if(err < 0) panic("Waiting for outer trampoline failed - errno = %d", 
-			  errno);
+	if(new_pid < 0)
+		return(new_pid);
+
+	CATCH_EINTR(err = waitpid(new_pid, &status, 0));
+	if(err < 0)
+		panic("Waiting for outer trampoline failed - errno = %d",
+		      errno);
+
 	if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
-		panic("outer trampoline didn't exit with SIGKILL");
+		panic("outer trampoline didn't exit with SIGKILL, "
+		      "status = %d", status);
 
 	return(arg.pid);
 }
@@ -138,7 +145,7 @@
 
 	os_stop_process(os_getpid());
 
-	if(read(fd, &c, sizeof(c)) != sizeof(c))
+	if(os_read_file(fd, &c, sizeof(c)) != sizeof(c))
 		panic("read failed in suspend_new_thread");
 }
 
@@ -168,7 +175,7 @@
 	pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
 	if(pid < 0)
 		panic("check_ptrace : clone failed, errno = %d", errno);
-	n = waitpid(pid, &status, WUNTRACED);
+	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0)
 		panic("check_ptrace : wait failed, errno = %d", errno);
 	if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
@@ -185,7 +192,7 @@
 
 	if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
 		panic("check_ptrace : ptrace failed, errno = %d", errno);
-	n = waitpid(pid, &status, 0);
+	CATCH_EINTR(n = waitpid(pid, &status, 0));
 	if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode))
 		panic("check_ptrace : child exited with status 0x%x", status);
 
@@ -193,6 +200,66 @@
 		panic("check_ptrace : munmap failed, errno = %d", errno);
 }
 
+static int force_sysemu_disabled = 0;
+
+static int __init nosysemu_cmd_param(char *str, int* add)
+{
+	force_sysemu_disabled = 1;
+	return 0;
+}
+
+__uml_setup("nosysemu", nosysemu_cmd_param,
+		"nosysemu\n"
+		"    Turns off syscall emulation patch for ptrace (SYSEMU) on.\n"
+		"    SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
+		"    behaviour of ptrace() and helps reducing host context switch rate.\n"
+		"    To make it working, you need a kernel patch for your host, too.\n"
+		"    See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n");
+
+static void __init check_sysemu(void)
+{
+	void *stack;
+	int pid, n, status;
+
+	if (mode_tt)
+		return;
+
+	printk("Checking syscall emulation patch for ptrace...");
+	sysemu_supported = 0;
+	pid = start_ptraced_child(&stack);
+	if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
+		struct user_regs_struct regs;
+
+		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+		if (n < 0)
+			panic("check_ptrace : wait failed, errno = %d", errno);
+		if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+			panic("check_ptrace : expected SIGTRAP, "
+			      "got status = %d", status);
+
+		if (ptrace(PTRACE_GETREGS, pid, 0, &regs) < 0)
+			panic("check_ptrace : failed to read child "
+			      "registers, errno = %d", errno);
+		regs.orig_eax = pid;
+		if (ptrace(PTRACE_SETREGS, pid, 0, &regs) < 0)
+			panic("check_ptrace : failed to modify child "
+			      "registers, errno = %d", errno);
+
+		stop_ptraced_child(pid, stack, 0);
+
+		sysemu_supported = 1;
+		printk("found\n");
+	}
+	else
+	{
+		stop_ptraced_child(pid, stack, 1);
+		sysemu_supported = 0;
+		printk("missing\n");
+	}
+
+	set_using_sysemu(!force_sysemu_disabled);
+}
+
 void __init check_ptrace(void)
 {
 	void *stack;
@@ -205,7 +272,7 @@
 		if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
 			panic("check_ptrace : ptrace failed, errno = %d", 
 			      errno);
-		n = waitpid(pid, &status, WUNTRACED);
+		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 		if(n < 0)
 			panic("check_ptrace : wait failed, errno = %d", errno);
 		if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
@@ -225,6 +292,7 @@
 	}
 	stop_ptraced_child(pid, stack, 0);
 	printk("OK\n");
+	check_sysemu();
 }
 
 int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
@@ -233,7 +301,7 @@
 	int n;
 
 	*jmp_ptr = &buf;
-	n = setjmp(buf);
+	n = sigsetjmp(buf, 1);
 	if(n != 0)
 		return(n);
 	(*fn)(arg);
@@ -273,7 +341,7 @@
 	stop_ptraced_child(pid, stack, 1);
 
 	printf("Checking for /proc/mm...");
-	if(access("/proc/mm", W_OK)){
+	if(os_access("/proc/mm", OS_ACC_W_OK) < 0){
 		printf("not found\n");
 		ret = 0;
 	}
diff -Nru a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
--- a/arch/um/kernel/process_kern.c	2003-10-07 19:53:41 -07:00
+++ b/arch/um/kernel/process_kern.c	2004-08-24 02:08:29 -07:00
@@ -16,6 +16,8 @@
 #include "linux/module.h"
 #include "linux/init.h"
 #include "linux/capability.h"
+#include "linux/vmalloc.h"
+#include "linux/spinlock.h"
 #include "asm/unistd.h"
 #include "asm/mman.h"
 #include "asm/segment.h"
@@ -23,7 +25,6 @@
 #include "asm/pgtable.h"
 #include "asm/processor.h"
 #include "asm/tlbflush.h"
-#include "asm/spinlock.h"
 #include "asm/uaccess.h"
 #include "asm/user.h"
 #include "user_util.h"
@@ -52,17 +53,12 @@
 
 struct task_struct *get_task(int pid, int require)
 {
-        struct task_struct *task, *ret;
+        struct task_struct *ret;
 
-        ret = NULL;
         read_lock(&tasklist_lock);
-        for_each_process(task){
-                if(task->pid == pid){
-                        ret = task;
-                        break;
-                }
-        }
+	ret = find_task_by_pid(pid);
         read_unlock(&tasklist_lock);
+
         if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
         return(ret);
 }
@@ -95,7 +91,8 @@
 	int flags = GFP_KERNEL;
 
 	if(atomic) flags |= GFP_ATOMIC;
-	if((page = __get_free_pages(flags, order)) == 0)
+	page = __get_free_pages(flags, order);
+	if(page == 0)
 		return(0);
 	stack_protections(page);
 	return(page);
@@ -103,22 +100,25 @@
 
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-	struct task_struct *p;
+	int pid;
 
 	current->thread.request.u.thread.proc = fn;
 	current->thread.request.u.thread.arg = arg;
-	p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
-	if(IS_ERR(p)) panic("do_fork failed in kernel_thread");
-	return(p->pid);
+	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL,
+		      NULL);
+	if(pid < 0)
+		panic("do_fork failed in kernel_thread, errno = %d", pid);
+	return(pid);
 }
 
 void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
 	       struct task_struct *tsk)
 {
-	unsigned cpu = smp_processor_id();
+	int cpu = smp_processor_id();
+
 	if (prev != next) 
-		clear_bit(cpu, &prev->cpu_vm_mask);
-	set_bit(cpu, &next->cpu_vm_mask);
+		cpu_clear(cpu, prev->cpu_vm_mask);
+	cpu_set(cpu, next->cpu_vm_mask);
 }
 
 void set_current(void *t)
@@ -129,7 +129,7 @@
 		{ external_pid(task), task });
 }
 
-void *switch_to(void *prev, void *next, void *last)
+void *_switch_to(void *prev, void *next, void *last)
 {
 	return(CHOOSE_MODE(switch_to_tt(prev, next), 
 			   switch_to_skas(prev, next)));
@@ -149,7 +149,7 @@
 void exit_thread(void)
 {
 	CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
-	unprotect_stack((unsigned long) current->thread_info);
+	unprotect_stack((unsigned long) current_thread);
 }
  
 void *get_current(void)
@@ -157,6 +157,10 @@
 	return(current);
 }
 
+void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
 		unsigned long stack_top, struct task_struct * p, 
 		struct pt_regs *regs)
@@ -190,7 +194,7 @@
 
 void default_idle(void)
 {
-	idle_timer();
+	uml_idle_timer();
 
 	atomic_inc(&init_mm.mm_count);
 	current->mm = &init_mm;
@@ -299,6 +303,11 @@
 	return(kmalloc(size, GFP_ATOMIC));
 }
 
+void *um_vmalloc(int size)
+{
+	return(vmalloc(size));
+}
+
 unsigned long get_fault_addr(void)
 {
 	return((unsigned long) current->thread.fault_addr);
@@ -367,10 +376,15 @@
 	return(clear_user(buf, size));
 }
 
+int strlen_user_proc(char *str)
+{
+	return(strlen_user(str));
+}
+
 int smp_sigio_handler(void)
 {
 #ifdef CONFIG_SMP
-	int cpu = current->thread_info->cpu;
+	int cpu = current_thread->cpu;
 	IPI_handler(cpu);
 	if(cpu != 0)
 		return(1);
@@ -385,7 +399,7 @@
 
 int cpu(void)
 {
-	return(current->thread_info->cpu);
+	return(current_thread->cpu);
 }
 
 /*
diff -Nru a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
--- a/arch/um/kernel/ptrace.c	2003-02-05 20:16:02 -08:00
+++ b/arch/um/kernel/ptrace.c	2004-08-24 02:08:18 -07:00
@@ -24,11 +24,6 @@
 { 
 }
 
-extern long do_mmap2(struct task_struct *task, unsigned long addr, 
-		     unsigned long len, unsigned long prot, 
-		     unsigned long flags, unsigned long fd,
-		     unsigned long pgoff);
-
 int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -302,8 +297,17 @@
 	return ret;
 }
 
-void syscall_trace(void)
+void syscall_trace(union uml_pt_regs *regs, int entryexit)
 {
+	if (unlikely(current->audit_context)) {
+		if (!entryexit)
+			audit_syscall_entry(current, regs->orig_eax,
+					    regs->ebx, regs->ecx,
+					    regs->edx, regs->esi);
+		else
+			audit_syscall_exit(current, regs->eax);
+	}
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return;
 	if (!(current->ptrace & PT_PTRACED))
@@ -311,11 +315,8 @@
 
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
- 	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- 					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
diff -Nru a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
--- a/arch/um/kernel/reboot.c	2003-10-07 19:53:41 -07:00
+++ b/arch/um/kernel/reboot.c	2004-08-24 02:08:18 -07:00
@@ -15,6 +15,7 @@
 #ifdef CONFIG_SMP
 static void kill_idlers(int me)
 {
+#ifdef CONFIG_MODE_TT
 	struct task_struct *p;
 	int i;
 
@@ -23,6 +24,7 @@
 		if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
 			os_kill_process(p->thread.mode.tt.extern_pid, 0);
 	}
+#endif
 }
 #endif
 
diff -Nru a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c
--- a/arch/um/kernel/sigio_kern.c	2002-10-14 06:53:49 -07:00
+++ b/arch/um/kernel/sigio_kern.c	2004-08-24 02:08:18 -07:00
@@ -6,18 +6,21 @@
 #include "linux/kernel.h"
 #include "linux/list.h"
 #include "linux/slab.h"
-#include "asm/irq.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
 #include "init.h"
 #include "sigio.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 /* Protected by sigio_lock() called from write_sigio_workaround */
 static int sigio_irq_fd = -1;
 
-void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	read_sigio_fd(sigio_irq_fd);
 	reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
+	return(IRQ_HANDLED);
 }
 
 int write_sigio_irq(int fd)
diff -Nru a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
--- a/arch/um/kernel/sigio_user.c	2003-01-18 12:26:19 -08:00
+++ b/arch/um/kernel/sigio_user.c	2004-08-24 02:08:25 -07:00
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <termios.h>
 #include <pty.h>
-#include <fcntl.h>
 #include <signal.h>
 #include <errno.h>
 #include <string.h>
@@ -17,6 +16,7 @@
 #include "init.h"
 #include "user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "sigio.h"
 #include "helper.h"
 #include "os.h"
@@ -26,7 +26,7 @@
 int pty_close_sigio = 0;
 
 /* Used as a flag during SIGIO testing early in boot */
-static int got_sigio = 0;
+static volatile int got_sigio = 0;
 
 void __init handler(int sig)
 {
@@ -45,19 +45,18 @@
 
 	info->err = 0;
 	if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
-		info->err = errno;
+		info->err = -errno;
 }
 
 void __init check_one_sigio(void (*proc)(int, int))
 {
 	struct sigaction old, new;
-	struct termios tt;
 	struct openpty_arg pty = { .master = -1, .slave = -1 };
-	int master, slave, flags;
+	int master, slave, err;
 
 	initial_thread_cb(openpty_cb, &pty);
 	if(pty.err){
-		printk("openpty failed, errno = %d\n", pty.err);
+		printk("openpty failed, errno = %d\n", -pty.err);
 		return;
 	}
 
@@ -69,23 +68,13 @@
 		return;
 	}
 
-	if(tcgetattr(master, &tt) < 0)
-		panic("check_sigio : tcgetattr failed, errno = %d\n", errno);
-	cfmakeraw(&tt);
-	if(tcsetattr(master, TCSADRAIN, &tt) < 0)
-		panic("check_sigio : tcsetattr failed, errno = %d\n", errno);
-
-	if((flags = fcntl(master, F_GETFL)) < 0)
-		panic("tty_fds : fcntl F_GETFL failed, errno = %d\n", errno);
-
-	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
-	   (fcntl(master, F_SETOWN, os_getpid()) < 0))
-		panic("check_sigio : fcntl F_SETFL or F_SETOWN failed, "
-		      "errno = %d\n", errno);
-
-	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
-		panic("check_sigio : fcntl F_SETFL failed, errno = %d\n", 
-		      errno);
+	err = __raw(master, 1, 0); //Not now, but complain so we now where we failed.
+	if (err < 0)
+		panic("check_sigio : __raw failed, errno = %d\n", -err);
+
+	err = os_sigio_async(master, slave);
+	if(err < 0)
+		panic("tty_fds : sigio_async failed, err = %d\n", -err);
 
 	if(sigaction(SIGIO, NULL, &old) < 0)
 		panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
@@ -97,8 +86,8 @@
 	got_sigio = 0;
 	(*proc)(master, slave);
 		
-	close(master);
-	close(slave);
+	os_close_file(master);
+	os_close_file(slave);
 
 	if(sigaction(SIGIO, &old, NULL) < 0)
 		panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
@@ -112,25 +101,25 @@
 	printk("Checking that host ptys support output SIGIO...");
 
 	memset(buf, 0, sizeof(buf));
-	while(write(master, buf, sizeof(buf)) > 0) ;
+
+	while(os_write_file(master, buf, sizeof(buf)) > 0) ;
 	if(errno != EAGAIN)
 		panic("check_sigio : write failed, errno = %d\n", errno);
-
-	while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+	while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
 
 	if(got_sigio){
 		printk("Yes\n");
 		pty_output_sigio = 1;
 	}
-	else if(errno == EAGAIN) printk("No, enabling workaround\n");
-	else panic("check_sigio : read failed, errno = %d\n", errno);
+	else if(n == -EAGAIN) printk("No, enabling workaround\n");
+	else panic("check_sigio : read failed, err = %d\n", n);
 }
 
 static void tty_close(int master, int slave)
 {
 	printk("Checking that host ptys support SIGIO on close...");
 
-	close(slave);
+	os_close_file(slave);
 	if(got_sigio){
 		printk("Yes\n");
 		pty_close_sigio = 1;
@@ -140,7 +129,8 @@
 
 void __init check_sigio(void)
 {
-	if(access("/dev/ptmx", R_OK) && access("/dev/ptyp0", R_OK)){
+	if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
+	   (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
 		printk("No pseudo-terminals available - skipping pty SIGIO "
 		       "check\n");
 		return;
@@ -201,11 +191,10 @@
 			p = &fds->poll[i];
 			if(p->revents == 0) continue;
 			if(p->fd == sigio_private[1]){
-				n = read(sigio_private[1], &c, sizeof(c));
+				n = os_read_file(sigio_private[1], &c, sizeof(c));
 				if(n != sizeof(c))
 					printk("write_sigio_thread : "
-					       "read failed, errno = %d\n",
-					       errno);
+					       "read failed, err = %d\n", -n);
 				tmp = current_poll;
 				current_poll = next_poll;
 				next_poll = tmp;
@@ -218,10 +207,10 @@
 					(fds->used - i) * sizeof(*fds->poll));
 			}
 
-			n = write(respond_fd, &c, sizeof(c));
+			n = os_write_file(respond_fd, &c, sizeof(c));
 			if(n != sizeof(c))
 				printk("write_sigio_thread : write failed, "
-				       "errno = %d\n", errno);
+				       "err = %d\n", -n);
 		}
 	}
 }
@@ -252,15 +241,15 @@
 	char c;
 
 	flags = set_signals(0);
-	n = write(sigio_private[0], &c, sizeof(c));
+	n = os_write_file(sigio_private[0], &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("update_thread : write failed, errno = %d\n", errno);
+		printk("update_thread : write failed, err = %d\n", -n);
 		goto fail;
 	}
 
-	n = read(sigio_private[0], &c, sizeof(c));
+	n = os_read_file(sigio_private[0], &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("update_thread : read failed, errno = %d\n", errno);
+		printk("update_thread : read failed, err = %d\n", -n);
 		goto fail;
 	}
 
@@ -271,10 +260,10 @@
 	if(write_sigio_pid != -1) 
 		os_kill_process(write_sigio_pid, 1);
 	write_sigio_pid = -1;
-	close(sigio_private[0]);
-	close(sigio_private[1]);	
-	close(write_sigio_fds[0]);
-	close(write_sigio_fds[1]);
+	os_close_file(sigio_private[0]);
+	os_close_file(sigio_private[1]);
+	os_close_file(write_sigio_fds[0]);
+	os_close_file(write_sigio_fds[1]);
 	sigio_unlock();
 	set_signals(flags);
 }
@@ -369,15 +358,15 @@
 		goto out;
 
 	err = os_pipe(write_sigio_fds, 1, 1);
-	if(err){
+	if(err < 0){
 		printk("write_sigio_workaround - os_pipe 1 failed, "
-		       "errno = %d\n", -err);
+		       "err = %d\n", -err);
 		goto out;
 	}
 	err = os_pipe(sigio_private, 1, 1);
-	if(err){
+	if(err < 0){
 		printk("write_sigio_workaround - os_pipe 2 failed, "
-		       "errno = %d\n", -err);
+		       "err = %d\n", -err);
 		goto out_close1;
 	}
 	if(setup_initial_poll(sigio_private[1]))
@@ -399,11 +388,11 @@
 	os_kill_process(write_sigio_pid, 1);
 	write_sigio_pid = -1;
  out_close2:
-	close(sigio_private[0]);
-	close(sigio_private[1]);	
+	os_close_file(sigio_private[0]);
+	os_close_file(sigio_private[1]);
  out_close1:
-	close(write_sigio_fds[0]);
-	close(write_sigio_fds[1]);
+	os_close_file(write_sigio_fds[0]);
+	os_close_file(write_sigio_fds[1]);
 	sigio_unlock();
 }
 
@@ -412,10 +401,16 @@
 	int n;
 	char c;
 
-	n = read(fd, &c, sizeof(c));
+	n = os_read_file(fd, &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("read_sigio_fd - read failed, errno = %d\n", errno);
-		return(-errno);
+		if(n < 0) {
+			printk("read_sigio_fd - read failed, err = %d\n", -n);
+			return(n);
+		}
+		else {
+			printk("read_sigio_fd - short read, bytes = %d\n", n);
+			return(-EIO);
+		}
 	}
 	return(n);
 }
diff -Nru a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
--- a/arch/um/kernel/signal_kern.c	2003-02-15 19:30:17 -08:00
+++ b/arch/um/kernel/signal_kern.c	2004-08-25 17:37:26 -07:00
@@ -31,17 +31,6 @@
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
 
-static void force_segv(int sig)
-{
-	if(sig == SIGSEGV){
-		struct k_sigaction *ka;
-
-		ka = &current->sig->action[SIGSEGV - 1];
-		ka->sa.sa_handler = SIG_DFL;
-	}
-	force_sig(SIGSEGV, current);
-}
-
 #define _S(nr) (1<<((nr)-1))
 
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
@@ -60,10 +49,10 @@
 	int err, ret;
 
 	ret = 0;
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 	switch(error){
 	case -ERESTART_RESTARTBLOCK:
-		current_thread_info()->restart_block.fn = 
-			do_no_restart_syscall;
 	case -ERESTARTNOHAND:
 		ret = -EINTR;
 		break;
@@ -124,27 +113,27 @@
 
 	return(0);
  segv:
-	force_segv(signr);
+	force_sigsegv(signr, current);
 	return(1);
 }
 
 static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
 {
+	struct k_sigaction ka_copy;
 	siginfo_t info;
-	struct k_sigaction *ka;
 	int err, sig;
 
 	if (!oldset)
 		oldset = &current->blocked;
 
-	sig = get_signal_to_deliver(&info, regs, NULL);
+	sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL);
 	if(sig == 0)
 		return(0);
 
 	/* Whee!  Actually deliver the signal.  */
-	ka = &current->sig->action[sig -1 ];
-	err = handle_signal(regs, sig, ka, &info, oldset, error);
-	if(!err) return(1);
+	err = handle_signal(regs, sig, &ka_copy, &info, oldset, error);
+	if(!err)
+		return(1);
 
 	/* Did we come from a system call? */
 	if(PT_REGS_SYSCALL_NR(regs) >= 0){
@@ -201,7 +190,7 @@
 	}
 }
 
-int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
+int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 {
 	sigset_t saveset, newset;
 
@@ -227,20 +216,59 @@
 	}
 }
 
+int sys_sigaction(int sig, const struct old_sigaction __user *act,
+			 struct old_sigaction __user *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
+}
+
+extern int userspace_pid[];
+
 static int copy_sc_from_user(struct pt_regs *to, void *from, 
 			     struct arch_frame_data *arch)
 {
 	int ret;
 
 	ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
-			  copy_sc_from_user_skas(&to->regs, from));
+			  copy_sc_from_user_skas(userspace_pid[0],
+						 &to->regs, from));
 	return(ret);
 }
 
 int sys_sigreturn(struct pt_regs regs)
 {
-	void *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
-	void *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
+	void __user *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
+	void __user *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
 	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -257,8 +285,8 @@
 
 int sys_rt_sigreturn(struct pt_regs regs)
 {
-	struct ucontext *uc = sp_to_uc(PT_REGS_SP(&current->thread.regs));
-	void *fp;
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct ucontext __user *uc = sp_to_uc(sp);
 	int sig_size = _NSIG_WORDS * sizeof(unsigned long);
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -266,7 +294,6 @@
 	sigdelsetmask(&current->blocked, ~_BLOCKABLE);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
-	fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext));
 	copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
 			  &signal_frame_si.common.arch);
 	return(PT_REGS_SYSCALL_RET(&current->thread.regs));
diff -Nru a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
--- a/arch/um/kernel/skas/Makefile	2002-12-16 23:21:40 -08:00
+++ b/arch/um/kernel/skas/Makefile	2004-08-24 02:08:22 -07:00
@@ -5,20 +5,24 @@
 
 obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \
 	process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \
-	sys-$(SUBARCH)/
+	uaccess.o sys-$(SUBARCH)/
+
+hostprogs-y	:= util/mk_ptregs
+clean-files	:= include/skas_ptregs.h
 
 USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-include/skas_ptregs.h : util/mk_ptregs
-	util/mk_ptregs > $@
-
-util/mk_ptregs :
-	$(MAKE) -C util
+$(TOPDIR)/arch/um/include/skas_ptregs.h : $(src)/util/mk_ptregs
+	@echo -n '  Generating $@'
+	@$< > $@.tmp
+	@if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+		echo ' (unchanged)'; \
+		rm -f $@.tmp; \
+	else \
+		echo ' (updated)'; \
+		mv -f $@.tmp $@; \
+	fi
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-	$(MAKE) -C util clean
-	$(RM) -f include/skas_ptregs.h
diff -Nru a/arch/um/kernel/skas/exec_user.c b/arch/um/kernel/skas/exec_user.c
--- a/arch/um/kernel/skas/exec_user.c	2002-11-19 11:39:52 -08:00
+++ b/arch/um/kernel/skas/exec_user.c	2004-08-24 02:08:27 -07:00
@@ -11,6 +11,7 @@
 #include <sys/ptrace.h>
 #include "user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "os.h"
 #include "time_user.h"
 
@@ -26,7 +27,7 @@
 
 int user_thread(unsigned long stack, int flags)
 {
-	int pid, status;
+	int pid, status, err;
 
 	pid = clone(user_thread_tramp, (void *) stack_sp(stack), 
 		    flags | CLONE_FILES | SIGCHLD, NULL);
@@ -35,7 +36,8 @@
 		return(pid);
 	}
 
-	if(waitpid(pid, &status, WUNTRACED) < 0){
+	CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+	if(err < 0){
 		printk("user_thread - waitpid failed, errno = %d\n", errno);
 		return(-errno);
 	}
diff -Nru a/arch/um/kernel/skas/include/mode.h b/arch/um/kernel/skas/include/mode.h
--- a/arch/um/kernel/skas/include/mode.h	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/skas/include/mode.h	2004-08-24 02:08:18 -07:00
@@ -12,14 +12,16 @@
 extern int have_fpx_regs;
 
 extern void user_time_init_skas(void);
-extern int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr);
-extern int copy_sc_to_user_skas(void *to_ptr, void *fp, 
+extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs,
+				  void *from_ptr);
+extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
 				union uml_pt_regs *regs, 
 				unsigned long fault_addr, int fault_type);
 extern void sig_handler_common_skas(int sig, void *sc_ptr);
 extern void halt_skas(void);
 extern void reboot_skas(void);
 extern void kill_off_processes_skas(void);
+extern int is_skas_winch(int pid, int fd, void *data);
 
 #endif
 
diff -Nru a/arch/um/kernel/skas/include/ptrace-skas.h b/arch/um/kernel/skas/include/ptrace-skas.h
--- a/arch/um/kernel/skas/include/ptrace-skas.h	2003-01-18 12:26:19 -08:00
+++ b/arch/um/kernel/skas/include/ptrace-skas.h	2004-08-24 02:08:26 -07:00
@@ -10,6 +10,16 @@
 
 #ifdef UML_CONFIG_MODE_SKAS
 
+/* syscall emulation path in ptrace */
+
+#ifndef PTRACE_SYSEMU
+#define PTRACE_SYSEMU 31
+#endif
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
+extern int sysemu_supported;
+
 #include "skas_ptregs.h"
 
 #define HOST_FRAME_SIZE 17
diff -Nru a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
--- a/arch/um/kernel/skas/include/skas.h	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/skas/include/skas.h	2004-08-24 02:08:18 -07:00
@@ -8,7 +8,7 @@
 
 #include "sysdep/ptrace.h"
 
-extern int userspace_pid;
+extern int userspace_pid[];
 
 extern void switch_threads(void *me, void *next);
 extern void thread_wait(void *sw, void *fb);
@@ -32,7 +32,7 @@
 extern int new_mm(int from);
 extern void save_registers(union uml_pt_regs *regs);
 extern void restore_registers(union uml_pt_regs *regs);
-extern void start_userspace(void);
+extern void start_userspace(int cpu);
 extern void init_registers(int pid);
 
 #endif
diff -Nru a/arch/um/kernel/skas/include/uaccess.h b/arch/um/kernel/skas/include/uaccess.h
--- a/arch/um/kernel/skas/include/uaccess.h	2002-12-29 15:31:27 -08:00
+++ b/arch/um/kernel/skas/include/uaccess.h	2004-08-24 02:08:18 -07:00
@@ -6,20 +6,12 @@
 #ifndef __SKAS_UACCESS_H
 #define __SKAS_UACCESS_H
 
-#include "linux/string.h"
-#include "linux/sched.h"
-#include "linux/err.h"
-#include "asm/processor.h"
-#include "asm/pgtable.h"
 #include "asm/errno.h"
-#include "asm/current.h"
-#include "asm/a.out.h"
-#include "kern_util.h"
 
 #define access_ok_skas(type, addr, size) \
 	((segment_eq(get_fs(), KERNEL_DS)) || \
 	 (((unsigned long) (addr) < TASK_SIZE) && \
-	  ((unsigned long) (addr) + (size) < TASK_SIZE)))
+	  ((unsigned long) (addr) + (size) <= TASK_SIZE)))
 
 static inline int verify_area_skas(int type, const void * addr, 
 				   unsigned long size)
@@ -27,197 +19,12 @@
 	return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
 }
 
-static inline unsigned long maybe_map(unsigned long virt, int is_write)
-{
-	pte_t pte;
-
-	void *phys = um_virt_to_phys(current, virt, &pte);
-	int dummy_code;
-
-	if(IS_ERR(phys) || (is_write && !pte_write(pte))){
-		if(handle_page_fault(virt, 0, is_write, 0, &dummy_code))
-			return(0);
-		phys = um_virt_to_phys(current, virt, NULL);
-	}
-	return((unsigned long) __va((unsigned long) phys));
-}
-
-static inline int buffer_op(unsigned long addr, int len, 
-			    int (*op)(unsigned long addr, int len, void *arg),
-			    void *arg)
-{
-	int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
-	int remain = len, n;
-
-	n = (*op)(addr, size, arg);
-	if(n != 0)
-		return(n < 0 ? remain : 0);
-
-	addr += size;
-	remain -= size;
-	if(remain == 0) 
-		return(0);
-
-	while(addr < ((addr + remain) & PAGE_MASK)){
-		n = (*op)(addr, PAGE_SIZE, arg);
-		if(n != 0)
-			return(n < 0 ? remain : 0);
-
-		addr += PAGE_SIZE;
-		remain -= PAGE_SIZE;
-	}
-	if(remain == 0)
-		return(0);
-
-	n = (*op)(addr, remain, arg);
-	if(n != 0)
-		return(n < 0 ? remain : 0);
-	return(0);
-}
-
-static inline int copy_chunk_from_user(unsigned long from, int len, void *arg)
-{
-	unsigned long *to_ptr = arg, to = *to_ptr;
-
-	from = maybe_map(from, 0);
-	if(from == 0)
-		return(-1);
-
-	memcpy((void *) to, (void *) from, len);
-	*to_ptr += len;
-	return(0);
-}
-
-static inline int copy_from_user_skas(void *to, const void *from, int n)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memcpy(to, from, n);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_READ, from, n) ?
-	       buffer_op((unsigned long) from, n, copy_chunk_from_user, &to) :
-	       n);
-}
-
-static inline int copy_chunk_to_user(unsigned long to, int len, void *arg)
-{
-	unsigned long *from_ptr = arg, from = *from_ptr;
-
-	to = maybe_map(to, 1);
-	if(to == 0)
-		return(-1);
-
-	memcpy((void *) to, (void *) from, len);
-	*from_ptr += len;
-	return(0);
-}
-
-static inline int copy_to_user_skas(void *to, const void *from, int n)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memcpy(to, from, n);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_WRITE, to, n) ?
-	       buffer_op((unsigned long) to, n, copy_chunk_to_user, &from) :
-	       n);
-}
-
-static inline int strncpy_chunk_from_user(unsigned long from, int len, 
-					  void *arg)
-{
-        char **to_ptr = arg, *to = *to_ptr;
-	int n;
-
-	from = maybe_map(from, 0);
-	if(from == 0)
-		return(-1);
-
-	strncpy(to, (void *) from, len);
-	n = strnlen(to, len);
-	*to_ptr += n;
-
-	if(n < len) 
-	        return(1);
-	return(0);
-}
-
-static inline int strncpy_from_user_skas(char *dst, const char *src, int count)
-{
-	int n;
-	char *ptr = dst;
-
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		strncpy(dst, src, count);
-		return(strnlen(dst, count));
-	}
-
-	if(!access_ok_skas(VERIFY_READ, src, 1))
-		return(-EFAULT);
-
-	n = buffer_op((unsigned long) src, count, strncpy_chunk_from_user, 
-		      &ptr);
-	if(n != 0)
-		return(-EFAULT);
-	return(strnlen(dst, count));
-}
-
-static inline int clear_chunk(unsigned long addr, int len, void *unused)
-{
-	addr = maybe_map(addr, 1);
-	if(addr == 0) 
-		return(-1);
-
-	memset((void *) addr, 0, len);
-	return(0);
-}
-
-static inline int __clear_user_skas(void *mem, int len)
-{
-	return(buffer_op((unsigned long) mem, len, clear_chunk, NULL));
-}
-
-static inline int clear_user_skas(void *mem, int len)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memset(mem, 0, len);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_WRITE, mem, len) ? 
-	       buffer_op((unsigned long) mem, len, clear_chunk, NULL) : len);
-}
-
-static inline int strnlen_chunk(unsigned long str, int len, void *arg)
-{
-	int *len_ptr = arg, n;
-
-	str = maybe_map(str, 0);
-	if(str == 0) 
-		return(-1);
-
-	n = strnlen((void *) str, len);
-	*len_ptr += n;
-
-	if(n < len)
-		return(1);
-	return(0);
-}
-
-static inline int strnlen_user_skas(const void *str, int len)
-{
-	int count = 0, n;
-
-	if(segment_eq(get_fs(), KERNEL_DS))
-		return(strnlen(str, len) + 1);
-
-	n = buffer_op((unsigned long) str, len, strnlen_chunk, &count);
-	if(n == 0)
-		return(count + 1);
-	return(-EFAULT);
-}
+extern int copy_from_user_skas(void *to, const void *from, int n);
+extern int copy_to_user_skas(void *to, const void *from, int n);
+extern int strncpy_from_user_skas(char *dst, const char *src, int count);
+extern int __clear_user_skas(void *mem, int len);
+extern int clear_user_skas(void *mem, int len);
+extern int strnlen_user_skas(const void *str, int len);
 
 #endif
 
diff -Nru a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
--- a/arch/um/kernel/skas/mem_user.c	2003-01-18 10:06:31 -08:00
+++ b/arch/um/kernel/skas/mem_user.c	2004-08-24 02:08:18 -07:00
@@ -7,6 +7,7 @@
 #include <sys/mman.h>
 #include <sys/ptrace.h>
 #include "mem_user.h"
+#include "mem.h"
 #include "user.h"
 #include "os.h"
 #include "proc_mm.h"
@@ -15,12 +16,12 @@
 	 int r, int w, int x)
 {
 	struct proc_mm_op map;
-	struct mem_region *region;
-	int prot, n;
+	__u64 offset;
+	int prot, n, phys_fd;
 
 	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
 		(x ? PROT_EXEC : 0);
-	region = phys_region(phys);
+	phys_fd = phys_mapping(phys, &offset);
 
 	map = ((struct proc_mm_op) { .op 	= MM_MMAP,
 				     .u 	= 
@@ -30,12 +31,12 @@
 					 .prot		= prot,
 					 .flags		= MAP_SHARED | 
 					                  MAP_FIXED,
-					 .fd		= region->fd,
-					 .offset	= phys_offset(phys)
+					 .fd		= phys_fd,
+					 .offset	= offset
 				       } } } );
 	n = os_write_file(fd, &map, sizeof(map));
 	if(n != sizeof(map)) 
-		printk("map : /proc/mm map failed, errno = %d\n", errno);
+		printk("map : /proc/mm map failed, err = %d\n", -n);
 }
 
 int unmap(int fd, void *addr, int len)
@@ -49,8 +50,13 @@
 					 { .addr 	= (unsigned long) addr,
 					   .len		= len } } } );
 	n = os_write_file(fd, &unmap, sizeof(unmap));
-	if((n != 0) && (n != sizeof(unmap)))
-		return(-errno);
+	if(n != sizeof(unmap)) {
+		if(n < 0)
+			return(n);
+		else if(n > 0)
+			return(-EIO);
+	}
+
 	return(0);
 }
 
@@ -71,11 +77,15 @@
 					   .prot	= prot } } } );
 
 	n = os_write_file(fd, &protect, sizeof(protect));
-	if((n != 0) && (n != sizeof(protect))){
+	if(n != sizeof(protect)) {
+		if(n == 0) return(0);
+
 		if(must_succeed)
-			panic("protect failed, errno = %d", errno);
-		return(-errno);
+			panic("protect failed, err = %d", -n);
+
+		return(-EIO);
 	}
+
 	return(0);
 }
 
diff -Nru a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
--- a/arch/um/kernel/skas/mmu.c	2002-11-20 19:42:39 -08:00
+++ b/arch/um/kernel/skas/mmu.c	2004-08-24 02:08:18 -07:00
@@ -22,9 +22,11 @@
 	else from = -1;
 
 	mm->context.skas.mm_fd = new_mm(from);
-	if(mm->context.skas.mm_fd < 0)
-		panic("init_new_context_skas - new_mm failed, errno = %d\n",
-		      mm->context.skas.mm_fd);
+	if(mm->context.skas.mm_fd < 0){
+		printk("init_new_context_skas - new_mm failed, errno = %d\n",
+		       mm->context.skas.mm_fd);
+		return(mm->context.skas.mm_fd);
+	}
 
 	return(0);
 }
diff -Nru a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
--- a/arch/um/kernel/skas/process.c	2003-02-05 07:18:58 -08:00
+++ b/arch/um/kernel/skas/process.c	2004-08-24 02:08:27 -07:00
@@ -4,6 +4,7 @@
  */
 
 #include <stdlib.h>
+#include <unistd.h>
 #include <errno.h>
 #include <signal.h>
 #include <setjmp.h>
@@ -24,6 +25,19 @@
 #include "os.h"
 #include "proc_mm.h"
 #include "skas_ptrace.h"
+#include "chan_user.h"
+#include "signal_user.h"
+
+int is_skas_winch(int pid, int fd, void *data)
+{
+	if(pid != getpid())
+		return(0);
+
+	register_winch_irq(-1, fd, -1, data);
+	return(1);
+}
+
+/* These are set once at boot time and not changed thereafter */
 
 unsigned long exec_regs[FRAME_SIZE];
 unsigned long exec_fp_regs[HOST_FP_SIZE];
@@ -43,37 +57,39 @@
 	segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
 }
 
-static void handle_trap(int pid, union uml_pt_regs *regs)
+/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
+static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
 {
 	int err, syscall_nr, status;
 
 	syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
+	UPT_SYSCALL_NR(regs) = syscall_nr;
 	if(syscall_nr < 1){
 		relay_signal(SIGTRAP, regs);
 		return;
 	}
-	UPT_SYSCALL_NR(regs) = syscall_nr;
 
-	err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
-	if(err < 0)
-	        panic("handle_trap - nullifying syscall failed errno = %d\n", 
-		      errno);
+	if (!local_using_sysemu)
+	{
+		err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+		if(err < 0)
+			panic("handle_trap - nullifying syscall failed errno = %d\n",
+			      errno);
+
+		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+		if(err < 0)
+			panic("handle_trap - continuing to end of syscall failed, "
+			      "errno = %d\n", errno);
 
-	err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
-	if(err < 0)
-	        panic("handle_trap - continuing to end of syscall failed, "
-		      "errno = %d\n", errno);
-
-	err = waitpid(pid, &status, WUNTRACED);
-	if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-		panic("handle_trap - failed to wait at end of syscall, "
-		      "errno = %d, status = %d\n", errno, status);
+		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+		if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+			panic("handle_trap - failed to wait at end of syscall, "
+			      "errno = %d, status = %d\n", errno, status);
+	}
 
 	handle_syscall(regs);
 }
 
-int userspace_pid;
-
 static int userspace_tramp(void *arg)
 {
 	init_new_thread_signals(0);
@@ -83,7 +99,11 @@
 	return(0);
 }
 
-void start_userspace(void)
+/* Each element set once, and only accessed by a single processor anyway */
+#define NR_CPUS 1
+int userspace_pid[NR_CPUS];
+
+void start_userspace(int cpu)
 {
 	void *stack;
 	unsigned long sp;
@@ -101,7 +121,7 @@
 		panic("start_userspace : clone failed, errno = %d", errno);
 
 	do {
-		n = waitpid(pid, &status, WUNTRACED);
+		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 		if(n < 0)
 			panic("start_userspace : wait failed, errno = %d", 
 			      errno);
@@ -114,21 +134,27 @@
 	if(munmap(stack, PAGE_SIZE) < 0)
 		panic("start_userspace : munmap failed, errno = %d\n", errno);
 
-	userspace_pid = pid;
+	userspace_pid[cpu] = pid;
 }
 
 void userspace(union uml_pt_regs *regs)
 {
-	int err, status, op;
+	int err, status, op, pid = userspace_pid[0];
+	int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
 
 	restore_registers(regs);
 		
-	err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0);
+	local_using_sysemu = get_using_sysemu();
+
+	if (local_using_sysemu)
+		err = ptrace(PTRACE_SYSEMU, pid, 0, 0);
+	else
+		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
 	if(err)
-		panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", 
-		       errno);
+		panic("userspace - PTRACE_%s failed, errno = %d\n",
+		       local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
 	while(1){
-		err = waitpid(userspace_pid, &status, WUNTRACED);
+		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
 		if(err < 0)
 			panic("userspace - waitpid failed, errno = %d\n", 
 			      errno);
@@ -139,16 +165,17 @@
 		if(WIFSTOPPED(status)){
 		  	switch(WSTOPSIG(status)){
 			case SIGSEGV:
-				handle_segv(userspace_pid);
+				handle_segv(pid);
 				break;
 			case SIGTRAP:
-			        handle_trap(userspace_pid, regs);
+			        handle_trap(pid, regs, local_using_sysemu);
 				break;
 			case SIGIO:
 			case SIGVTALRM:
 			case SIGILL:
 			case SIGBUS:
 			case SIGFPE:
+			case SIGWINCH:
 				user_signal(WSTOPSIG(status), regs);
 				break;
 			default:
@@ -160,25 +187,46 @@
 
 		restore_registers(regs);
 
-		op = singlestepping_skas() ? PTRACE_SINGLESTEP : 
-			PTRACE_SYSCALL;
-		err = ptrace(op, userspace_pid, 0, 0);
+		/*Now we ended the syscall, so re-read local_using_sysemu.*/
+		local_using_sysemu = get_using_sysemu();
+
+		if (local_using_sysemu)
+			op = singlestepping_skas() ? PTRACE_SINGLESTEP :
+				PTRACE_SYSEMU;
+		else
+			op = singlestepping_skas() ? PTRACE_SINGLESTEP :
+				PTRACE_SYSCALL;
+
+		err = ptrace(op, pid, 0, 0);
 		if(err)
-			panic("userspace - PTRACE_SYSCALL failed, "
-			      "errno = %d\n", errno);
+			panic("userspace - PTRACE_%s failed, "
+			      "errno = %d\n",
+			      local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
 	}
 }
 
 void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
 		void (*handler)(int))
 {
+	unsigned long flags;
 	jmp_buf switch_buf, fork_buf;
 
 	*switch_buf_ptr = &switch_buf;
 	*fork_buf_ptr = &fork_buf;
 
-	if(setjmp(fork_buf) == 0)
+	/* Somewhat subtle - siglongjmp restores the signal mask before doing
+	 * the longjmp.  This means that when jumping from one stack to another
+	 * when the target stack has interrupts enabled, an interrupt may occur
+	 * on the source stack.  This is bad when starting up a process because
+	 * it's not supposed to get timer ticks until it has been scheduled.
+	 * So, we disable interrupts around the sigsetjmp to ensure that
+	 * they can't happen until we get back here where they are safe.
+	 */
+	flags = get_signals();
+	block_signals();
+	if(sigsetjmp(fork_buf, 1) == 0)
 		new_thread_proc(stack, handler);
+	set_signals(flags);
 
 	remove_sigstack();
 }
@@ -189,16 +237,16 @@
 
 	*switch_buf = &buf;
 	fork_buf = fb;
-	if(setjmp(buf) == 0)
-		longjmp(*fork_buf, 1);
+	if(sigsetjmp(buf, 1) == 0)
+		siglongjmp(*fork_buf, 1);
 }
 
-static int move_registers(int int_op, int fp_op, union uml_pt_regs *regs,
-			  unsigned long *fp_regs)
+static int move_registers(int pid, int int_op, int fp_op,
+			  union uml_pt_regs *regs, unsigned long *fp_regs)
 {
-	if(ptrace(int_op, userspace_pid, 0, regs->skas.regs) < 0)
+	if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
 		return(-errno);
-	if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0)
+	if(ptrace(fp_op, pid, 0, fp_regs) < 0)
 		return(-errno);
 	return(0);
 }
@@ -217,10 +265,11 @@
 		fp_regs = regs->skas.fp;
 	}
 
-	err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs);
+	err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs,
+			     fp_regs);
 	if(err)
 		panic("save_registers - saving registers failed, errno = %d\n",
-		      err);
+		      -err);
 }
 
 void restore_registers(union uml_pt_regs *regs)
@@ -237,10 +286,11 @@
 		fp_regs = regs->skas.fp;
 	}
 
-	err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs);
+	err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs,
+			     fp_regs);
 	if(err)
 		panic("restore_registers - saving registers failed, "
-		      "errno = %d\n", err);
+		      "errno = %d\n", -err);
 }
 
 void switch_threads(void *me, void *next)
@@ -248,8 +298,8 @@
 	jmp_buf my_buf, **me_ptr = me, *next_buf = next;
 	
 	*me_ptr = &my_buf;
-	if(setjmp(my_buf) == 0)
-		longjmp(*next_buf, 1);
+	if(sigsetjmp(my_buf, 1) == 0)
+		siglongjmp(*next_buf, 1);
 }
 
 static jmp_buf initial_jmpbuf;
@@ -265,14 +315,14 @@
 	int n;
 
 	*fork_buf_ptr = &initial_jmpbuf;
-	n = setjmp(initial_jmpbuf);
+	n = sigsetjmp(initial_jmpbuf, 1);
 	if(n == 0)
 		new_thread_proc((void *) stack, new_thread_handler);
 	else if(n == 1)
 		remove_sigstack();
 	else if(n == 2){
 		(*cb_proc)(cb_arg);
-		longjmp(*cb_back, 1);
+		siglongjmp(*cb_back, 1);
 	}
 	else if(n == 3){
 		kmalloc_ok = 0;
@@ -282,7 +332,7 @@
 		kmalloc_ok = 0;
 		return(1);
 	}
-	longjmp(**switch_buf, 1);
+	siglongjmp(**switch_buf, 1);
 }
 
 void remove_sigstack(void)
@@ -304,8 +354,8 @@
 	cb_back = &here;
 
 	block_signals();
-	if(setjmp(here) == 0)
-		longjmp(initial_jmpbuf, 2);
+	if(sigsetjmp(here, 1) == 0)
+		siglongjmp(initial_jmpbuf, 2);
 	unblock_signals();
 
 	cb_proc = NULL;
@@ -316,22 +366,23 @@
 void halt_skas(void)
 {
 	block_signals();
-	longjmp(initial_jmpbuf, 3);
+	siglongjmp(initial_jmpbuf, 3);
 }
 
 void reboot_skas(void)
 {
 	block_signals();
-	longjmp(initial_jmpbuf, 4);
+	siglongjmp(initial_jmpbuf, 4);
 }
 
 int new_mm(int from)
 {
 	struct proc_mm_op copy;
-	int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0);
+	int n, fd = os_open_file("/proc/mm",
+				 of_cloexec(of_write(OPENFLAGS())), 0);
 
 	if(fd < 0)
-		return(-errno);
+		return(fd);
 
 	if(from != -1){
 		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
@@ -340,8 +391,9 @@
 		n = os_write_file(fd, &copy, sizeof(copy));
 		if(n != sizeof(copy)) 
 			printk("new_mm : /proc/mm copy_segments failed, "
-			       "errno = %d\n", errno);
+			       "err = %d\n", -n);
 	}
+
 	return(fd);
 }
 
@@ -349,7 +401,8 @@
 {
 	int err;
 
-	err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd);
+#warning need cpu pid in switch_mm_skas
+	err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd);
 	if(err)
 		panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
 		      errno);
@@ -357,7 +410,8 @@
 
 void kill_off_processes_skas(void)
 {
-	os_kill_process(userspace_pid, 1);
+#warning need to loop over userspace_pids in kill_off_processes_skas
+	os_kill_process(userspace_pid[0], 1);
 }
 
 void init_registers(int pid)
diff -Nru a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
--- a/arch/um/kernel/skas/process_kern.c	2003-08-18 19:46:23 -07:00
+++ b/arch/um/kernel/skas/process_kern.c	2004-08-24 02:08:26 -07:00
@@ -6,6 +6,12 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/ptrace.h"
+#include "linux/proc_fs.h"
+#include "linux/file.h"
+#include "linux/errno.h"
+#include "linux/init.h"
+#include "asm/uaccess.h"
+#include "asm/atomic.h"
 #include "kern_util.h"
 #include "time_user.h"
 #include "signal_user.h"
@@ -17,6 +23,61 @@
 #include "kern.h"
 #include "mode.h"
 
+static atomic_t using_sysemu;
+int sysemu_supported;
+
+void set_using_sysemu(int value)
+{
+	atomic_set(&using_sysemu, sysemu_supported && value);
+}
+
+int get_using_sysemu(void)
+{
+	return atomic_read(&using_sysemu);
+}
+
+int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
+{
+	if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
+		*eof = 1;
+
+	return strlen(buf);
+}
+
+int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
+{
+	char tmp[2];
+
+	if (copy_from_user(tmp, buf, 1))
+		return -EFAULT;
+
+	if (tmp[0] == '0' || tmp[0] == '1')
+		set_using_sysemu(tmp[0] - '0');
+	return count; /*We use the first char, but pretend to write everything*/
+}
+
+int __init make_proc_sysemu(void)
+{
+	struct proc_dir_entry *ent;
+	if (mode_tt || !sysemu_supported)
+		return 0;
+
+	ent = create_proc_entry("sysemu", 0600, &proc_root);
+
+	if (ent == NULL)
+	{
+		printk("Failed to register /proc/sysemu\n");
+		return(0);
+	}
+
+	ent->read_proc  = proc_read_sysemu;
+	ent->write_proc = proc_write_sysemu;
+
+	return 0;
+}
+
+late_initcall(make_proc_sysemu);
+
 int singlestepping_skas(void)
 {
 	int ret = current->ptrace & PT_DTRACE;
@@ -61,11 +122,13 @@
 	thread_wait(&current->thread.mode.skas.switch_buf, 
 		    current->thread.mode.skas.fork_buf);
 
-#ifdef CONFIG_SMP
-	schedule_tail(NULL);
-#endif
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
 	current->thread.prev_sched = NULL;
 
+	/* The return value is 1 if the kernel thread execs a process,
+	 * 0 if it just exits
+	 */
 	n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
 	if(n == 1)
 		userspace(&current->thread.regs.regs);
@@ -93,11 +156,11 @@
 		    current->thread.mode.skas.fork_buf);
   	
 	force_flush_all();
-#ifdef CONFIG_SMP
+	if(current->thread.prev_sched == NULL)
+		panic("blech");
+
 	schedule_tail(current->thread.prev_sched);
-#endif
 	current->thread.prev_sched = NULL;
-	unblock_signals();
 
 	userspace(&current->thread.regs.regs);
 }
@@ -136,7 +199,7 @@
 
 void init_idle_skas(void)
 {
-	cpu_tasks[current->thread_info->cpu].pid = os_getpid();
+	cpu_tasks[current_thread->cpu].pid = os_getpid();
 	default_idle();
 }
 
@@ -160,11 +223,11 @@
 
 int start_uml_skas(void)
 {
-	start_userspace();
+	start_userspace(0);
 	capture_signal_stack();
+	uml_idle_timer();
 
 	init_new_thread_signals(1);
-	idle_timer();
 
 	init_task.thread.request.u.thread.proc = start_kernel_proc;
 	init_task.thread.request.u.thread.arg = NULL;
@@ -175,12 +238,14 @@
 
 int external_pid_skas(struct task_struct *task)
 {
-	return(userspace_pid);
+#warning Need to look up userspace_pid by cpu
+	return(userspace_pid[0]);
 }
 
 int thread_pid_skas(struct task_struct *task)
 {
-	return(userspace_pid);
+#warning Need to look up userspace_pid by cpu
+	return(userspace_pid[0]);
 }
 
 /*
diff -Nru a/arch/um/kernel/skas/sys-i386/Makefile b/arch/um/kernel/skas/sys-i386/Makefile
--- a/arch/um/kernel/skas/sys-i386/Makefile	2002-12-16 23:21:40 -08:00
+++ b/arch/um/kernel/skas/sys-i386/Makefile	2004-08-24 02:08:18 -07:00
@@ -10,5 +10,3 @@
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
diff -Nru a/arch/um/kernel/skas/sys-i386/sigcontext.c b/arch/um/kernel/skas/sys-i386/sigcontext.c
--- a/arch/um/kernel/skas/sys-i386/sigcontext.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/skas/sys-i386/sigcontext.c	2004-08-24 02:08:18 -07:00
@@ -12,10 +12,9 @@
 #include "kern_util.h"
 #include "user.h"
 #include "sigcontext.h"
+#include "mode.h"
 
-extern int userspace_pid;
-
-int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr)
+int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr)
 {
   	struct sigcontext sc, *from = from_ptr;
 	unsigned long fpregs[FP_FRAME_SIZE];
@@ -41,13 +40,12 @@
 	regs->skas.regs[EIP] = sc.eip;
 	regs->skas.regs[CS] = sc.cs;
 	regs->skas.regs[EFL] = sc.eflags;
-	regs->skas.regs[UESP] = sc.esp_at_signal;
 	regs->skas.regs[SS] = sc.ss;
 	regs->skas.fault_addr = sc.cr2;
 	regs->skas.fault_type = FAULT_WRITE(sc.err);
 	regs->skas.trap_type = sc.trapno;
 
-	err = ptrace(PTRACE_SETFPREGS, userspace_pid, 0, fpregs);
+	err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs);
 	if(err < 0){
 	  	printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
 		       "errno = %d\n", errno);
@@ -57,8 +55,9 @@
 	return(0);
 }
 
-int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs, 
-			 unsigned long fault_addr, int fault_type)
+int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
+			 union uml_pt_regs *regs, unsigned long fault_addr,
+			 int fault_type)
 {
   	struct sigcontext sc, *to = to_ptr;
 	struct _fpstate *to_fp;
@@ -86,7 +85,7 @@
 	sc.err = TO_SC_ERR(fault_type);
 	sc.trapno = regs->skas.trap_type;
 
-	err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs);
+	err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs);
 	if(err < 0){
 	  	printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
 		       "errno = %d\n", errno);
diff -Nru a/arch/um/kernel/skas/syscall_kern.c b/arch/um/kernel/skas/syscall_kern.c
--- a/arch/um/kernel/skas/syscall_kern.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/skas/syscall_kern.c	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
diff -Nru a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c
--- a/arch/um/kernel/skas/syscall_user.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/skas/syscall_user.c	2004-08-24 02:08:18 -07:00
@@ -22,7 +22,7 @@
 
 	index = record_syscall_start(UPT_SYSCALL_NR(regs));
 
-	syscall_trace();
+	syscall_trace(regs, 1);
 	result = execute_syscall(regs);
 
 	REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
@@ -30,7 +30,7 @@
 	   (result == -ERESTARTNOINTR))
 		do_signal(result);
 
-	syscall_trace();
+	syscall_trace(regs, 0);
 	record_syscall_end(index, result);
 }
 
diff -Nru a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c
--- a/arch/um/kernel/skas/trap_user.c	2002-12-29 17:37:09 -08:00
+++ b/arch/um/kernel/skas/trap_user.c	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -35,14 +35,10 @@
 	errno = save_errno;
 }
 
-extern int missed_ticks[];
-
 void user_signal(int sig, union uml_pt_regs *regs)
 {
 	struct signal_info *info;
 
-	if(sig == SIGVTALRM)
-		missed_ticks[cpu()]++;
 	regs->skas.is_user = 1;
 	regs->skas.fault_addr = 0;
 	regs->skas.fault_type = 0;
diff -Nru a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/kernel/skas/uaccess.c	2004-08-24 02:08:28 -07:00
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/stddef.h"
+#include "linux/kernel.h"
+#include "linux/string.h"
+#include "linux/fs.h"
+#include "linux/highmem.h"
+#include "asm/page.h"
+#include "asm/pgtable.h"
+#include "asm/uaccess.h"
+#include "kern_util.h"
+
+extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+			     pte_t *pte_out);
+
+static unsigned long maybe_map(unsigned long virt, int is_write)
+{
+	pte_t pte;
+	int err;
+
+	void *phys = um_virt_to_phys(current, virt, &pte);
+	int dummy_code;
+
+	if(IS_ERR(phys) || (is_write && !pte_write(pte))){
+		err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
+		if(err)
+			return(0);
+		phys = um_virt_to_phys(current, virt, NULL);
+	}
+	return((unsigned long) phys);
+}
+
+static int do_op(unsigned long addr, int len, int is_write,
+		 int (*op)(unsigned long addr, int len, void *arg), void *arg)
+{
+	struct page *page;
+	int n;
+
+	addr = maybe_map(addr, is_write);
+	if(addr == -1)
+		return(-1);
+
+	page = phys_to_page(addr);
+	addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
+	n = (*op)(addr, len, arg);
+	kunmap(page);
+
+	return(n);
+}
+
+static int buffer_op(unsigned long addr, int len, int is_write,
+		     int (*op)(unsigned long addr, int len, void *arg),
+		     void *arg)
+{
+	int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
+	int remain = len, n;
+
+	n = do_op(addr, size, is_write, op, arg);
+	if(n != 0)
+		return(n < 0 ? remain : 0);
+
+	addr += size;
+	remain -= size;
+	if(remain == 0)
+		return(0);
+
+	while(addr < ((addr + remain) & PAGE_MASK)){
+		n = do_op(addr, PAGE_SIZE, is_write, op, arg);
+		if(n != 0)
+			return(n < 0 ? remain : 0);
+
+		addr += PAGE_SIZE;
+		remain -= PAGE_SIZE;
+	}
+	if(remain == 0)
+		return(0);
+
+	n = do_op(addr, remain, is_write, op, arg);
+	if(n != 0)
+		return(n < 0 ? remain : 0);
+	return(0);
+}
+
+static int copy_chunk_from_user(unsigned long from, int len, void *arg)
+{
+	unsigned long *to_ptr = arg, to = *to_ptr;
+
+	memcpy((void *) to, (void *) from, len);
+	*to_ptr += len;
+	return(0);
+}
+
+int copy_from_user_skas(void *to, const void *from, int n)
+{
+	if(segment_eq(get_fs(), KERNEL_DS)){
+		memcpy(to, from, n);
+		return(0);
+	}
+
+	return(access_ok_skas(VERIFY_READ, from, n) ?
+	       buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
+	       n);
+}
+
+static int copy_chunk_to_user(unsigned long to, int len, void *arg)
+{
+	unsigned long *from_ptr = arg, from = *from_ptr;
+
+	memcpy((void *) to, (void *) from, len);
+	*from_ptr += len;
+	return(0);
+}
+
+int copy_to_user_skas(void *to, const void *from, int n)
+{
+	if(segment_eq(get_fs(), KERNEL_DS)){
+		memcpy(to, from, n);
+		return(0);
+	}
+
+	return(access_ok_skas(VERIFY_WRITE, to, n) ?
+	       buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
+	       n);
+}
+
+static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
+{
+	char **to_ptr = arg, *to = *to_ptr;
+	int n;
+
+	strncpy(to, (void *) from, len);
+	n = strnlen(to, len);
+	*to_ptr += n;
+
+	if(n < len)
+	        return(1);
+	return(0);
+}
+
+int strncpy_from_user_skas(char *dst, const char *src, int count)
+{
+	int n;
+	char *ptr = dst;
+
+	if(segment_eq(get_fs(), KERNEL_DS)){
+		strncpy(dst, src, count);
+		return(strnlen(dst, count));
+	}
+
+	if(!access_ok_skas(VERIFY_READ, src, 1))
+		return(-EFAULT);
+
+	n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
+		      &ptr);
+	if(n != 0)
+		return(-EFAULT);
+	return(strnlen(dst, count));
+}
+
+static int clear_chunk(unsigned long addr, int len, void *unused)
+{
+	memset((void *) addr, 0, len);
+	return(0);
+}
+
+int __clear_user_skas(void *mem, int len)
+{
+	return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL));
+}
+
+int clear_user_skas(void *mem, int len)
+{
+	if(segment_eq(get_fs(), KERNEL_DS)){
+		memset(mem, 0, len);
+		return(0);
+	}
+
+	return(access_ok_skas(VERIFY_WRITE, mem, len) ?
+	       buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
+}
+
+static int strnlen_chunk(unsigned long str, int len, void *arg)
+{
+	int *len_ptr = arg, n;
+
+	n = strnlen((void *) str, len);
+	*len_ptr += n;
+
+	if(n < len)
+		return(1);
+	return(0);
+}
+
+int strnlen_user_skas(const void *str, int len)
+{
+	int count = 0, n;
+
+	if(segment_eq(get_fs(), KERNEL_DS))
+		return(strnlen(str, len) + 1);
+
+	n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count);
+	if(n == 0)
+		return(count + 1);
+	return(-EFAULT);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
--- a/arch/um/kernel/skas/util/Makefile	2002-11-21 09:51:44 -08:00
+++ b/arch/um/kernel/skas/util/Makefile	2004-08-24 02:08:18 -07:00
@@ -1,10 +1,9 @@
 all: mk_ptregs
 
 mk_ptregs : mk_ptregs.o
-	$(CC) -o mk_ptregs mk_ptregs.o
+	$(HOSTCC) -o mk_ptregs mk_ptregs.o
 
 mk_ptregs.o : mk_ptregs.c
-	$(CC) -c $< 
+	$(HOSTCC) -c $<
 
-clean : 
-	$(RM) -f mk_ptregs *.o *~
+clean-files := mk_ptregs *.o *~
diff -Nru a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs.c
--- a/arch/um/kernel/skas/util/mk_ptregs.c	2002-11-21 09:51:44 -08:00
+++ b/arch/um/kernel/skas/util/mk_ptregs.c	2004-08-24 02:08:18 -07:00
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
diff -Nru a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
--- a/arch/um/kernel/smp.c	2004-05-10 04:25:47 -07:00
+++ b/arch/um/kernel/smp.c	2004-08-24 02:08:29 -07:00
@@ -1,9 +1,15 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #include "linux/config.h"
+#include "linux/percpu.h"
+#include "asm/pgalloc.h"
+#include "asm/tlb.h"
+
+/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 #ifdef CONFIG_SMP
 
@@ -23,7 +29,7 @@
 #include "os.h"
 
 /* CPU online map, set by smp_boot_cpus */
-unsigned long cpu_online_map = cpumask_of_cpu(0);
+unsigned long cpu_online_map = CPU_MASK_NONE;
 
 EXPORT_SYMBOL(cpu_online_map);
 
@@ -33,14 +39,6 @@
  */
 struct cpuinfo_um cpu_data[NR_CPUS];
 
-spinlock_t um_bh_lock = SPIN_LOCK_UNLOCKED;
-
-atomic_t global_bh_count;
-
-/* Not used by UML */
-unsigned char global_irq_holder = NO_PROC_ID;
-unsigned volatile long global_irq_lock;
-
 /* Set when the idlers are all forked */
 int smp_threads_ready = 0;
 
@@ -55,80 +53,44 @@
 
 void smp_send_reschedule(int cpu)
 {
-	write(cpu_data[cpu].ipi_pipe[1], "R", 1);
+	os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1);
 	num_reschedules_sent++;
 }
 
-static void show(char * str)
-{
-	int cpu = smp_processor_id();
-
-	printk(KERN_INFO "\n%s, CPU %d:\n", str, cpu);
-}
-	
-#define MAXCOUNT 100000000
-
-static inline void wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-	do {
-		if (!--count) {
-			show("wait_on_bh");
-			count = ~0;
-		}
-		/* nothing .. wait for the other bh's to go away */
-	} while (atomic_read(&global_bh_count) != 0);
-}
-
-/*
- * This is called when we want to synchronize with
- * bottom half handlers. We need to wait until
- * no other CPU is executing any bottom half handler.
- *
- * Don't wait if we're already running in an interrupt
- * context or are inside a bh handler. 
- */
-void synchronize_bh(void)
-{
-	if (atomic_read(&global_bh_count) && !in_interrupt())
-		wait_on_bh();
-}
-
 void smp_send_stop(void)
 {
 	int i;
 
 	printk(KERN_INFO "Stopping all CPUs...");
 	for(i = 0; i < num_online_cpus(); i++){
-		if(i == current->thread_info->cpu)
+		if(i == current_thread->cpu)
 			continue;
-		write(cpu_data[i].ipi_pipe[1], "S", 1);
+		os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
 	}
 	printk("done\n");
 }
 
-static cpumask_t smp_commenced_mask;
-static cpumask_t smp_callin_map = CPU_MASK_NONE;
+static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
+static cpumask_t cpu_callin_map = CPU_MASK_NONE;
 
 static int idle_proc(void *cpup)
 {
 	int cpu = (int) cpup, err;
 
 	err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
-	if(err)
-		panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, 
-		      -err);
+	if(err < 0)
+		panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
 
 	activate_ipi(cpu_data[cpu].ipi_pipe[0], 
 		     current->thread.mode.tt.extern_pid);
  
 	wmb();
-	if (cpu_test_and_set(cpu, &smp_callin_map)) {
+	if (cpu_test_and_set(cpu, cpu_callin_map)) {
 		printk("huh, CPU#%d already present??\n", cpu);
 		BUG();
 	}
 
-	while (!cpu_isset(cpu, &smp_commenced_mask))
+	while (!cpu_isset(cpu, smp_commenced_mask))
 		cpu_relax();
 
 	cpu_set(cpu, cpu_online_map);
@@ -143,14 +105,16 @@
 
         current->thread.request.u.thread.proc = idle_proc;
         current->thread.request.u.thread.arg = (void *) cpu;
-	new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, NULL);
-	if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
+	new_task = fork_idle(cpu);
+	if(IS_ERR(new_task))
+		panic("copy_process failed in idle_thread, error = %ld",
+		      PTR_ERR(new_task));
 
 	cpu_tasks[cpu] = ((struct cpu_task) 
 		          { .pid = 	new_task->thread.mode.tt.extern_pid,
 			    .task = 	new_task } );
 	idle_threads[cpu] = new_task;
-	CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c, 
+	CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
 			  sizeof(c)),
 		    ({ panic("skas mode doesn't support SMP"); }));
 	return(new_task);
@@ -160,15 +124,17 @@
 {
 	struct task_struct *idle;
 	unsigned long waittime;
-	int err, cpu;
+	int err, cpu, me = smp_processor_id();
 
-	cpu_set(0, cpu_online_map);
-	cpu_set(0, smp_callin_map);
+	cpu_clear(me, cpu_online_map);
+	cpu_set(me, cpu_online_map);
+	cpu_set(me, cpu_callin_map);
 
-	err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
-	if(err)	panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
+	err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
+	if(err < 0)
+		panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
 
-	activate_ipi(cpu_data[0].ipi_pipe[0], 
+	activate_ipi(cpu_data[me].ipi_pipe[0],
 		     current->thread.mode.tt.extern_pid);
 
 	for(cpu = 1; cpu < ncpus; cpu++){
@@ -180,10 +146,10 @@
 		unhash_process(idle);
 
 		waittime = 200000000;
-		while (waittime-- && !cpu_isset(cpu, smp_callin_map))
+		while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
 			cpu_relax();
 
-		if (cpu_isset(cpu, smp_callin_map))
+		if (cpu_isset(cpu, cpu_callin_map))
 			printk("done\n");
 		else printk("failed\n");
 	}
@@ -216,7 +182,7 @@
 	int fd;
 
 	fd = cpu_data[cpu].ipi_pipe[0];
-	while (read(fd, &c, 1) == 1) {
+	while (os_read_file(fd, &c, 1) == 1) {
 		switch (c) {
 		case 'C':
 			smp_call_function_slave(cpu);
@@ -276,9 +242,9 @@
 	info = _info;
 
 	for (i=0;i<NR_CPUS;i++)
-		if((i != current->thread_info->cpu) && 
+		if((i != current_thread->cpu) &&
 		   cpu_isset(i, cpu_online_map))
-			write(cpu_data[i].ipi_pipe[1], "C", 1);
+			os_write_file(cpu_data[i].ipi_pipe[1], "C", 1);
 
 	while (atomic_read(&scf_started) != cpus)
 		barrier();
diff -Nru a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
--- a/arch/um/kernel/sys_call_table.c	2004-02-25 02:31:13 -08:00
+++ b/arch/um/kernel/sys_call_table.c	2004-08-24 02:08:18 -07:00
@@ -5,7 +5,6 @@
 
 #include "linux/config.h"
 #include "linux/unistd.h"
-#include "linux/version.h"
 #include "linux/sys.h"
 #include "linux/swap.h"
 #include "linux/syscalls.h"
@@ -14,251 +13,50 @@
 #include "sysdep/syscalls.h"
 #include "kern_util.h"
 
-extern syscall_handler_t sys_restart_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_exit;
+#ifdef CONFIG_NFSD
+#define NFSSERVCTL sys_nfsservctl
+#else
+#define NFSSERVCTL sys_ni_syscall
+#endif
+
+#define LAST_GENERIC_SYSCALL __NR_vserver
+
+#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
+#define LAST_SYSCALL LAST_GENERIC_SYSCALL
+#else
+#define LAST_SYSCALL LAST_ARCH_SYSCALL
+#endif
+
 extern syscall_handler_t sys_fork;
-extern syscall_handler_t sys_creat;
-extern syscall_handler_t sys_link;
-extern syscall_handler_t sys_unlink;
-extern syscall_handler_t sys_chdir;
-extern syscall_handler_t sys_mknod;
-extern syscall_handler_t sys_chmod;
-extern syscall_handler_t sys_lchown16;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_stat;
-extern syscall_handler_t sys_getpid;
-extern syscall_handler_t sys_oldumount;
-extern syscall_handler_t sys_setuid16;
-extern syscall_handler_t sys_getuid16;
+extern syscall_handler_t sys_execve;
+extern syscall_handler_t um_time;
+extern syscall_handler_t um_mount;
+extern syscall_handler_t um_stime;
 extern syscall_handler_t sys_ptrace;
-extern syscall_handler_t sys_alarm;
-extern syscall_handler_t sys_fstat;
-extern syscall_handler_t sys_pause;
-extern syscall_handler_t sys_utime;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_access;
-extern syscall_handler_t sys_nice;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_sync;
-extern syscall_handler_t sys_kill;
-extern syscall_handler_t sys_rename;
-extern syscall_handler_t sys_mkdir;
-extern syscall_handler_t sys_rmdir;
 extern syscall_handler_t sys_pipe;
-extern syscall_handler_t sys_times;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_brk;
-extern syscall_handler_t sys_setgid16;
-extern syscall_handler_t sys_getgid16;
-extern syscall_handler_t sys_signal;
-extern syscall_handler_t sys_geteuid16;
-extern syscall_handler_t sys_getegid16;
-extern syscall_handler_t sys_acct;
-extern syscall_handler_t sys_umount;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ioctl;
-extern syscall_handler_t sys_fcntl;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_setpgid;
-extern syscall_handler_t sys_ni_syscall;
 extern syscall_handler_t sys_olduname;
-extern syscall_handler_t sys_umask;
-extern syscall_handler_t sys_chroot;
-extern syscall_handler_t sys_ustat;
-extern syscall_handler_t sys_dup2;
-extern syscall_handler_t sys_getppid;
-extern syscall_handler_t sys_getpgrp;
 extern syscall_handler_t sys_sigaction;
-extern syscall_handler_t sys_sgetmask;
-extern syscall_handler_t sys_ssetmask;
-extern syscall_handler_t sys_setreuid16;
-extern syscall_handler_t sys_setregid16;
 extern syscall_handler_t sys_sigsuspend;
-extern syscall_handler_t sys_sigpending;
-extern syscall_handler_t sys_sethostname;
-extern syscall_handler_t sys_setrlimit;
-extern syscall_handler_t sys_old_getrlimit;
-extern syscall_handler_t sys_getrusage;
-extern syscall_handler_t sys_gettimeofday;
-extern syscall_handler_t sys_settimeofday;
-extern syscall_handler_t sys_getgroups16;
-extern syscall_handler_t sys_setgroups16;
-extern syscall_handler_t sys_symlink;
-extern syscall_handler_t sys_lstat;
-extern syscall_handler_t sys_readlink;
-extern syscall_handler_t sys_swapon;
-extern syscall_handler_t sys_uselib;
-extern syscall_handler_t sys_reboot;
 extern syscall_handler_t old_readdir;
-extern syscall_handler_t sys_munmap;
-extern syscall_handler_t sys_truncate;
-extern syscall_handler_t sys_ftruncate;
-extern syscall_handler_t sys_fchmod;
-extern syscall_handler_t sys_fchown16;
-extern syscall_handler_t sys_getpriority;
-extern syscall_handler_t sys_setpriority;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_statfs;
-extern syscall_handler_t sys_fstatfs;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_socketcall;
-extern syscall_handler_t sys_syslog;
-extern syscall_handler_t sys_setitimer;
-extern syscall_handler_t sys_getitimer;
-extern syscall_handler_t sys_newstat;
-extern syscall_handler_t sys_newlstat;
-extern syscall_handler_t sys_newfstat;
 extern syscall_handler_t sys_uname;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_vhangup;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_swapoff;
-extern syscall_handler_t sys_sysinfo;
 extern syscall_handler_t sys_ipc;
-extern syscall_handler_t sys_fsync;
 extern syscall_handler_t sys_sigreturn;
-extern syscall_handler_t sys_rt_sigreturn;
 extern syscall_handler_t sys_clone;
-extern syscall_handler_t sys_setdomainname;
-extern syscall_handler_t sys_newuname;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_adjtimex;
-extern syscall_handler_t sys_mprotect;
-extern syscall_handler_t sys_sigprocmask;
-extern syscall_handler_t sys_init_module;
-extern syscall_handler_t sys_delete_module;
-extern syscall_handler_t sys_quotactl;
-extern syscall_handler_t sys_getpgid;
-extern syscall_handler_t sys_fchdir;
-extern syscall_handler_t sys_bdflush;
-extern syscall_handler_t sys_sysfs;
-extern syscall_handler_t sys_personality;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_setfsuid16;
-extern syscall_handler_t sys_setfsgid16;
-extern syscall_handler_t sys_llseek;
-extern syscall_handler_t sys_getdents;
-extern syscall_handler_t sys_flock;
-extern syscall_handler_t sys_msync;
-extern syscall_handler_t sys_readv;
-extern syscall_handler_t sys_writev;
-extern syscall_handler_t sys_getsid;
-extern syscall_handler_t sys_fdatasync;
-extern syscall_handler_t sys_mlock;
-extern syscall_handler_t sys_munlock;
-extern syscall_handler_t sys_mlockall;
-extern syscall_handler_t sys_munlockall;
-extern syscall_handler_t sys_sched_setparam;
-extern syscall_handler_t sys_sched_getparam;
-extern syscall_handler_t sys_sched_setscheduler;
-extern syscall_handler_t sys_sched_getscheduler;
-extern syscall_handler_t sys_sched_get_priority_max;
-extern syscall_handler_t sys_sched_get_priority_min;
-extern syscall_handler_t sys_sched_rr_get_interval;
-extern syscall_handler_t sys_nanosleep;
-extern syscall_handler_t sys_mremap;
-extern syscall_handler_t sys_setresuid16;
-extern syscall_handler_t sys_getresuid16;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_poll;
-extern syscall_handler_t sys_nfsservctl;
-extern syscall_handler_t sys_setresgid16;
-extern syscall_handler_t sys_getresgid16;
-extern syscall_handler_t sys_prctl;
-extern syscall_handler_t sys_ni_syscall;
+extern syscall_handler_t sys_rt_sigreturn;
 extern syscall_handler_t sys_rt_sigaction;
-extern syscall_handler_t sys_rt_sigprocmask;
-extern syscall_handler_t sys_rt_sigpending;
-extern syscall_handler_t sys_rt_sigtimedwait;
-extern syscall_handler_t sys_rt_sigqueueinfo;
-extern syscall_handler_t sys_rt_sigsuspend;
-extern syscall_handler_t sys_pread64;
-extern syscall_handler_t sys_pwrite64;
-extern syscall_handler_t sys_chown16;
-extern syscall_handler_t sys_getcwd;
-extern syscall_handler_t sys_capget;
-extern syscall_handler_t sys_capset;
 extern syscall_handler_t sys_sigaltstack;
-extern syscall_handler_t sys_sendfile;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
 extern syscall_handler_t sys_vfork;
-extern syscall_handler_t sys_getrlimit;
 extern syscall_handler_t sys_mmap2;
-extern syscall_handler_t sys_truncate64;
-extern syscall_handler_t sys_ftruncate64;
-extern syscall_handler_t sys_stat64;
-extern syscall_handler_t sys_lstat64;
-extern syscall_handler_t sys_fstat64;
-extern syscall_handler_t sys_lchown;
-extern syscall_handler_t sys_getuid;
-extern syscall_handler_t sys_getgid;
-extern syscall_handler_t sys_geteuid;
-extern syscall_handler_t sys_getegid;
-extern syscall_handler_t sys_setreuid;
-extern syscall_handler_t sys_setregid;
-extern syscall_handler_t sys_getgroups;
-extern syscall_handler_t sys_setgroups;
-extern syscall_handler_t sys_fchown;
-extern syscall_handler_t sys_setresuid;
-extern syscall_handler_t sys_getresuid;
-extern syscall_handler_t sys_setresgid;
-extern syscall_handler_t sys_getresgid;
-extern syscall_handler_t sys_chown;
-extern syscall_handler_t sys_setuid;
-extern syscall_handler_t sys_setgid;
-extern syscall_handler_t sys_setfsuid;
-extern syscall_handler_t sys_setfsgid;
-extern syscall_handler_t sys_pivot_root;
-extern syscall_handler_t sys_mincore;
-extern syscall_handler_t sys_madvise;
-extern syscall_handler_t sys_fcntl64;
-extern syscall_handler_t sys_getdents64;
-extern syscall_handler_t sys_gettid;
-extern syscall_handler_t sys_readahead;
-extern syscall_handler_t sys_tkill;
-extern syscall_handler_t sys_sendfile64;
-extern syscall_handler_t sys_futex;
-extern syscall_handler_t sys_sched_setaffinity;
-extern syscall_handler_t sys_sched_getaffinity;
-extern syscall_handler_t sys_io_setup;
-extern syscall_handler_t sys_io_destroy;
-extern syscall_handler_t sys_io_getevents;
-extern syscall_handler_t sys_io_submit;
-extern syscall_handler_t sys_io_cancel;
-extern syscall_handler_t sys_exit_group;
-extern syscall_handler_t sys_lookup_dcookie;
-extern syscall_handler_t sys_epoll_create;
-extern syscall_handler_t sys_epoll_ctl;
-extern syscall_handler_t sys_epoll_wait;
-extern syscall_handler_t sys_remap_file_pages;
-extern syscall_handler_t sys_set_tid_address;
-
-#ifdef CONFIG_NFSD
-#define NFSSERVCTL sys_nfsservctl
-#else
-#define NFSSERVCTL sys_ni_syscall
-#endif
-
-extern syscall_handler_t um_mount;
-extern syscall_handler_t um_time;
-extern syscall_handler_t um_stime;
-
-#define LAST_GENERIC_SYSCALL __NR_set_tid_address
-
-#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
-#define LAST_SYSCALL LAST_GENERIC_SYSCALL
-#else
-#define LAST_SYSCALL LAST_ARCH_SYSCALL
-#endif
+extern syscall_handler_t sys_timer_create;
+extern syscall_handler_t old_mmap_i386;
+extern syscall_handler_t old_select;
+extern syscall_handler_t sys_modify_ldt;
+extern syscall_handler_t sys_rt_sigsuspend;
 
 syscall_handler_t *sys_call_table[] = {
-	[ __NR_restart_syscall ] = sys_restart_syscall,
-	[ __NR_exit ] = sys_exit,
-	[ __NR_fork ] = sys_fork,
+	[ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
+	[ __NR_exit ] (syscall_handler_t *) sys_exit,
+	[ __NR_fork ] (syscall_handler_t *) sys_fork,
 	[ __NR_read ] = (syscall_handler_t *) sys_read,
 	[ __NR_write ] = (syscall_handler_t *) sys_write,
 
@@ -266,229 +64,249 @@
 	[ __NR_open ] = (syscall_handler_t *) sys_open,
 	[ __NR_close ] = (syscall_handler_t *) sys_close,
 	[ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid,
-	[ __NR_creat ] = sys_creat,
-	[ __NR_link ] = sys_link,
-	[ __NR_unlink ] = sys_unlink,
+	[ __NR_creat ] (syscall_handler_t *) sys_creat,
+	[ __NR_link ] (syscall_handler_t *) sys_link,
+	[ __NR_unlink ] (syscall_handler_t *) sys_unlink,
 	[ __NR_execve ] = (syscall_handler_t *) sys_execve,
 
 	/* declared differently in kern_util.h */
-	[ __NR_chdir ] = sys_chdir,
+	[ __NR_chdir ] (syscall_handler_t *) sys_chdir,
 	[ __NR_time ] = um_time,
-	[ __NR_mknod ] = sys_mknod,
-	[ __NR_chmod ] = sys_chmod,
-	[ __NR_lchown ] = sys_lchown16,
-	[ __NR_break ] = sys_ni_syscall,
-	[ __NR_oldstat ] = sys_stat,
+	[ __NR_mknod ] (syscall_handler_t *) sys_mknod,
+	[ __NR_chmod ] (syscall_handler_t *) sys_chmod,
+	[ __NR_lchown ] (syscall_handler_t *) sys_lchown16,
+	[ __NR_break ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_oldstat ] (syscall_handler_t *) sys_stat,
 	[ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
-	[ __NR_getpid ] = sys_getpid,
+	[ __NR_getpid ] (syscall_handler_t *) sys_getpid,
 	[ __NR_mount ] = um_mount,
-	[ __NR_umount ] = sys_oldumount,
-	[ __NR_setuid ] = sys_setuid16,
-	[ __NR_getuid ] = sys_getuid16,
+	[ __NR_umount ] (syscall_handler_t *) sys_oldumount,
+	[ __NR_setuid ] (syscall_handler_t *) sys_setuid16,
+	[ __NR_getuid ] (syscall_handler_t *) sys_getuid16,
 	[ __NR_stime ] = um_stime,
-	[ __NR_ptrace ] = sys_ptrace,
-	[ __NR_alarm ] = sys_alarm,
-	[ __NR_oldfstat ] = sys_fstat,
-	[ __NR_pause ] = sys_pause,
-	[ __NR_utime ] = sys_utime,
-	[ __NR_stty ] = sys_ni_syscall,
-	[ __NR_gtty ] = sys_ni_syscall,
-	[ __NR_access ] = sys_access,
-	[ __NR_nice ] = sys_nice,
-	[ __NR_ftime ] = sys_ni_syscall,
-	[ __NR_sync ] = sys_sync,
-	[ __NR_kill ] = sys_kill,
-	[ __NR_rename ] = sys_rename,
-	[ __NR_mkdir ] = sys_mkdir,
-	[ __NR_rmdir ] = sys_rmdir,
+	[ __NR_ptrace ] (syscall_handler_t *) sys_ptrace,
+	[ __NR_alarm ] (syscall_handler_t *) sys_alarm,
+	[ __NR_oldfstat ] (syscall_handler_t *) sys_fstat,
+	[ __NR_pause ] (syscall_handler_t *) sys_pause,
+	[ __NR_utime ] (syscall_handler_t *) sys_utime,
+	[ __NR_stty ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_gtty ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_access ] (syscall_handler_t *) sys_access,
+	[ __NR_nice ] (syscall_handler_t *) sys_nice,
+	[ __NR_ftime ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_sync ] (syscall_handler_t *) sys_sync,
+	[ __NR_kill ] (syscall_handler_t *) sys_kill,
+	[ __NR_rename ] (syscall_handler_t *) sys_rename,
+	[ __NR_mkdir ] (syscall_handler_t *) sys_mkdir,
+	[ __NR_rmdir ] (syscall_handler_t *) sys_rmdir,
 
 	/* Declared differently in asm/unistd.h */
 	[ __NR_dup ] = (syscall_handler_t *) sys_dup,
-	[ __NR_pipe ] = sys_pipe,
-	[ __NR_times ] = sys_times,
-	[ __NR_prof ] = sys_ni_syscall,
-	[ __NR_brk ] = sys_brk,
-	[ __NR_setgid ] = sys_setgid16,
-	[ __NR_getgid ] = sys_getgid16,
-	[ __NR_signal ] = sys_signal,
-	[ __NR_geteuid ] = sys_geteuid16,
-	[ __NR_getegid ] = sys_getegid16,
-	[ __NR_acct ] = sys_acct,
-	[ __NR_umount2 ] = sys_umount,
-	[ __NR_lock ] = sys_ni_syscall,
-	[ __NR_ioctl ] = sys_ioctl,
-	[ __NR_fcntl ] = sys_fcntl,
-	[ __NR_mpx ] = sys_ni_syscall,
-	[ __NR_setpgid ] = sys_setpgid,
-	[ __NR_ulimit ] = sys_ni_syscall,
-	[ __NR_oldolduname ] = sys_olduname,
-	[ __NR_umask ] = sys_umask,
-	[ __NR_chroot ] = sys_chroot,
-	[ __NR_ustat ] = sys_ustat,
-	[ __NR_dup2 ] = sys_dup2,
-	[ __NR_getppid ] = sys_getppid,
-	[ __NR_getpgrp ] = sys_getpgrp,
+	[ __NR_pipe ] (syscall_handler_t *) sys_pipe,
+	[ __NR_times ] (syscall_handler_t *) sys_times,
+	[ __NR_prof ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_brk ] (syscall_handler_t *) sys_brk,
+	[ __NR_setgid ] (syscall_handler_t *) sys_setgid16,
+	[ __NR_getgid ] (syscall_handler_t *) sys_getgid16,
+	[ __NR_signal ] (syscall_handler_t *) sys_signal,
+	[ __NR_geteuid ] (syscall_handler_t *) sys_geteuid16,
+	[ __NR_getegid ] (syscall_handler_t *) sys_getegid16,
+	[ __NR_acct ] (syscall_handler_t *) sys_acct,
+	[ __NR_umount2 ] (syscall_handler_t *) sys_umount,
+	[ __NR_lock ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_ioctl ] (syscall_handler_t *) sys_ioctl,
+	[ __NR_fcntl ] (syscall_handler_t *) sys_fcntl,
+	[ __NR_mpx ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_setpgid ] (syscall_handler_t *) sys_setpgid,
+	[ __NR_ulimit ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_oldolduname ] (syscall_handler_t *) sys_olduname,
+	[ __NR_umask ] (syscall_handler_t *) sys_umask,
+	[ __NR_chroot ] (syscall_handler_t *) sys_chroot,
+	[ __NR_ustat ] (syscall_handler_t *) sys_ustat,
+	[ __NR_dup2 ] (syscall_handler_t *) sys_dup2,
+	[ __NR_getppid ] (syscall_handler_t *) sys_getppid,
+	[ __NR_getpgrp ] (syscall_handler_t *) sys_getpgrp,
 	[ __NR_setsid ] = (syscall_handler_t *) sys_setsid,
-	[ __NR_sigaction ] = sys_sigaction,
-	[ __NR_sgetmask ] = sys_sgetmask,
-	[ __NR_ssetmask ] = sys_ssetmask,
-	[ __NR_setreuid ] = sys_setreuid16,
-	[ __NR_setregid ] = sys_setregid16,
-	[ __NR_sigsuspend ] = sys_sigsuspend,
-	[ __NR_sigpending ] = sys_sigpending,
-	[ __NR_sethostname ] = sys_sethostname,
-	[ __NR_setrlimit ] = sys_setrlimit,
-	[ __NR_getrlimit ] = sys_old_getrlimit,
-	[ __NR_getrusage ] = sys_getrusage,
-	[ __NR_gettimeofday ] = sys_gettimeofday,
-	[ __NR_settimeofday ] = sys_settimeofday,
-	[ __NR_getgroups ] = sys_getgroups16,
-	[ __NR_setgroups ] = sys_setgroups16,
-	[ __NR_symlink ] = sys_symlink,
-	[ __NR_oldlstat ] = sys_lstat,
-	[ __NR_readlink ] = sys_readlink,
-	[ __NR_uselib ] = sys_uselib,
+	[ __NR_sigaction ] (syscall_handler_t *) sys_sigaction,
+	[ __NR_sgetmask ] (syscall_handler_t *) sys_sgetmask,
+	[ __NR_ssetmask ] (syscall_handler_t *) sys_ssetmask,
+	[ __NR_setreuid ] (syscall_handler_t *) sys_setreuid16,
+	[ __NR_setregid ] (syscall_handler_t *) sys_setregid16,
+	[ __NR_sigsuspend ] (syscall_handler_t *) sys_sigsuspend,
+	[ __NR_sigpending ] (syscall_handler_t *) sys_sigpending,
+	[ __NR_sethostname ] (syscall_handler_t *) sys_sethostname,
+	[ __NR_setrlimit ] (syscall_handler_t *) sys_setrlimit,
+	[ __NR_getrlimit ] (syscall_handler_t *) sys_old_getrlimit,
+	[ __NR_getrusage ] (syscall_handler_t *) sys_getrusage,
+	[ __NR_gettimeofday ] (syscall_handler_t *) sys_gettimeofday,
+	[ __NR_settimeofday ] (syscall_handler_t *) sys_settimeofday,
+	[ __NR_getgroups ] (syscall_handler_t *) sys_getgroups16,
+	[ __NR_setgroups ] (syscall_handler_t *) sys_setgroups16,
+	[ __NR_symlink ] (syscall_handler_t *) sys_symlink,
+	[ __NR_oldlstat ] (syscall_handler_t *) sys_lstat,
+	[ __NR_readlink ] (syscall_handler_t *) sys_readlink,
+	[ __NR_uselib ] (syscall_handler_t *) sys_uselib,
 	[ __NR_swapon ] = (syscall_handler_t *) sys_swapon,
-	[ __NR_reboot ] = sys_reboot,
+	[ __NR_reboot ] (syscall_handler_t *) sys_reboot,
 	[ __NR_readdir ] = old_readdir,
-	[ __NR_munmap ] = sys_munmap,
-	[ __NR_truncate ] = sys_truncate,
-	[ __NR_ftruncate ] = sys_ftruncate,
-	[ __NR_fchmod ] = sys_fchmod,
-	[ __NR_fchown ] = sys_fchown16,
-	[ __NR_getpriority ] = sys_getpriority,
-	[ __NR_setpriority ] = sys_setpriority,
-	[ __NR_profil ] = sys_ni_syscall,
-	[ __NR_statfs ] = sys_statfs,
-	[ __NR_fstatfs ] = sys_fstatfs,
-	[ __NR_ioperm ] = sys_ni_syscall,
-	[ __NR_socketcall ] = sys_socketcall,
-	[ __NR_syslog ] = sys_syslog,
-	[ __NR_setitimer ] = sys_setitimer,
-	[ __NR_getitimer ] = sys_getitimer,
-	[ __NR_stat ] = sys_newstat,
-	[ __NR_lstat ] = sys_newlstat,
-	[ __NR_fstat ] = sys_newfstat,
-	[ __NR_olduname ] = sys_uname,
-	[ __NR_iopl ] = sys_ni_syscall,
-	[ __NR_vhangup ] = sys_vhangup,
-	[ __NR_idle ] = sys_ni_syscall,
+	[ __NR_munmap ] (syscall_handler_t *) sys_munmap,
+	[ __NR_truncate ] (syscall_handler_t *) sys_truncate,
+	[ __NR_ftruncate ] (syscall_handler_t *) sys_ftruncate,
+	[ __NR_fchmod ] (syscall_handler_t *) sys_fchmod,
+	[ __NR_fchown ] (syscall_handler_t *) sys_fchown16,
+	[ __NR_getpriority ] (syscall_handler_t *) sys_getpriority,
+	[ __NR_setpriority ] (syscall_handler_t *) sys_setpriority,
+	[ __NR_profil ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_statfs ] (syscall_handler_t *) sys_statfs,
+	[ __NR_fstatfs ] (syscall_handler_t *) sys_fstatfs,
+	[ __NR_ioperm ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_socketcall ] (syscall_handler_t *) sys_socketcall,
+	[ __NR_syslog ] (syscall_handler_t *) sys_syslog,
+	[ __NR_setitimer ] (syscall_handler_t *) sys_setitimer,
+	[ __NR_getitimer ] (syscall_handler_t *) sys_getitimer,
+	[ __NR_stat ] (syscall_handler_t *) sys_newstat,
+	[ __NR_lstat ] (syscall_handler_t *) sys_newlstat,
+	[ __NR_fstat ] (syscall_handler_t *) sys_newfstat,
+	[ __NR_olduname ] (syscall_handler_t *) sys_uname,
+	[ __NR_iopl ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_vhangup ] (syscall_handler_t *) sys_vhangup,
+	[ __NR_idle ] (syscall_handler_t *) sys_ni_syscall,
 	[ __NR_wait4 ] = (syscall_handler_t *) sys_wait4,
 	[ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff,
-	[ __NR_sysinfo ] = sys_sysinfo,
-	[ __NR_ipc ] = sys_ipc,
-	[ __NR_fsync ] = sys_fsync,
-	[ __NR_sigreturn ] = sys_sigreturn,
-	[ __NR_clone ] = sys_clone,
-	[ __NR_setdomainname ] = sys_setdomainname,
-	[ __NR_uname ] = sys_newuname,
-	[ __NR_adjtimex ] = sys_adjtimex,
-	[ __NR_mprotect ] = sys_mprotect,
-	[ __NR_sigprocmask ] = sys_sigprocmask,
-	[ __NR_create_module ] = sys_ni_syscall,
-	[ __NR_init_module ] = sys_init_module,
-	[ __NR_delete_module ] = sys_delete_module,
-	[ __NR_get_kernel_syms ] = sys_ni_syscall,
-	[ __NR_quotactl ] = sys_quotactl,
-	[ __NR_getpgid ] = sys_getpgid,
-	[ __NR_fchdir ] = sys_fchdir,
-	[ __NR_bdflush ] = sys_bdflush,
-	[ __NR_sysfs ] = sys_sysfs,
-	[ __NR_personality ] = sys_personality,
-	[ __NR_afs_syscall ] = sys_ni_syscall,
-	[ __NR_setfsuid ] = sys_setfsuid16,
-	[ __NR_setfsgid ] = sys_setfsgid16,
-	[ __NR__llseek ] = sys_llseek,
-	[ __NR_getdents ] = sys_getdents,
+	[ __NR_sysinfo ] (syscall_handler_t *) sys_sysinfo,
+	[ __NR_ipc ] (syscall_handler_t *) sys_ipc,
+	[ __NR_fsync ] (syscall_handler_t *) sys_fsync,
+	[ __NR_sigreturn ] (syscall_handler_t *) sys_sigreturn,
+	[ __NR_clone ] (syscall_handler_t *) sys_clone,
+	[ __NR_setdomainname ] (syscall_handler_t *) sys_setdomainname,
+	[ __NR_uname ] (syscall_handler_t *) sys_newuname,
+	[ __NR_adjtimex ] (syscall_handler_t *) sys_adjtimex,
+	[ __NR_mprotect ] (syscall_handler_t *) sys_mprotect,
+	[ __NR_sigprocmask ] (syscall_handler_t *) sys_sigprocmask,
+	[ __NR_create_module ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_init_module ] (syscall_handler_t *) sys_init_module,
+	[ __NR_delete_module ] (syscall_handler_t *) sys_delete_module,
+	[ __NR_get_kernel_syms ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_quotactl ] (syscall_handler_t *) sys_quotactl,
+	[ __NR_getpgid ] (syscall_handler_t *) sys_getpgid,
+	[ __NR_fchdir ] (syscall_handler_t *) sys_fchdir,
+	[ __NR_bdflush ] (syscall_handler_t *) sys_bdflush,
+	[ __NR_sysfs ] (syscall_handler_t *) sys_sysfs,
+	[ __NR_personality ] (syscall_handler_t *) sys_personality,
+	[ __NR_afs_syscall ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_setfsuid ] (syscall_handler_t *) sys_setfsuid16,
+	[ __NR_setfsgid ] (syscall_handler_t *) sys_setfsgid16,
+	[ __NR__llseek ] (syscall_handler_t *) sys_llseek,
+	[ __NR_getdents ] (syscall_handler_t *) sys_getdents,
 	[ __NR__newselect ] = (syscall_handler_t *) sys_select,
-	[ __NR_flock ] = sys_flock,
-	[ __NR_msync ] = sys_msync,
-	[ __NR_readv ] = sys_readv,
-	[ __NR_writev ] = sys_writev,
-	[ __NR_getsid ] = sys_getsid,
-	[ __NR_fdatasync ] = sys_fdatasync,
+	[ __NR_flock ] (syscall_handler_t *) sys_flock,
+	[ __NR_msync ] (syscall_handler_t *) sys_msync,
+	[ __NR_readv ] (syscall_handler_t *) sys_readv,
+	[ __NR_writev ] (syscall_handler_t *) sys_writev,
+	[ __NR_getsid ] (syscall_handler_t *) sys_getsid,
+	[ __NR_fdatasync ] (syscall_handler_t *) sys_fdatasync,
 	[ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl,
-	[ __NR_mlock ] = sys_mlock,
-	[ __NR_munlock ] = sys_munlock,
-	[ __NR_mlockall ] = sys_mlockall,
-	[ __NR_munlockall ] = sys_munlockall,
-	[ __NR_sched_setparam ] = sys_sched_setparam,
-	[ __NR_sched_getparam ] = sys_sched_getparam,
-	[ __NR_sched_setscheduler ] = sys_sched_setscheduler,
-	[ __NR_sched_getscheduler ] = sys_sched_getscheduler,
+	[ __NR_mlock ] (syscall_handler_t *) sys_mlock,
+	[ __NR_munlock ] (syscall_handler_t *) sys_munlock,
+	[ __NR_mlockall ] (syscall_handler_t *) sys_mlockall,
+	[ __NR_munlockall ] (syscall_handler_t *) sys_munlockall,
+	[ __NR_sched_setparam ] (syscall_handler_t *) sys_sched_setparam,
+	[ __NR_sched_getparam ] (syscall_handler_t *) sys_sched_getparam,
+	[ __NR_sched_setscheduler ] (syscall_handler_t *) sys_sched_setscheduler,
+	[ __NR_sched_getscheduler ] (syscall_handler_t *) sys_sched_getscheduler,
 	[ __NR_sched_yield ] = (syscall_handler_t *) yield,
-	[ __NR_sched_get_priority_max ] = sys_sched_get_priority_max,
-	[ __NR_sched_get_priority_min ] = sys_sched_get_priority_min,
-	[ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval,
-	[ __NR_nanosleep ] = sys_nanosleep,
-	[ __NR_mremap ] = sys_mremap,
-	[ __NR_setresuid ] = sys_setresuid16,
-	[ __NR_getresuid ] = sys_getresuid16,
-	[ __NR_vm86 ] = sys_ni_syscall,
-	[ __NR_query_module ] = sys_ni_syscall,
-	[ __NR_poll ] = sys_poll,
-	[ __NR_nfsservctl ] = NFSSERVCTL,
-	[ __NR_setresgid ] = sys_setresgid16,
-	[ __NR_getresgid ] = sys_getresgid16,
-	[ __NR_prctl ] = sys_prctl,
-	[ __NR_rt_sigreturn ] = sys_rt_sigreturn,
-	[ __NR_rt_sigaction ] = sys_rt_sigaction,
-	[ __NR_rt_sigprocmask ] = sys_rt_sigprocmask,
-	[ __NR_rt_sigpending ] = sys_rt_sigpending,
-	[ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait,
-	[ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo,
-	[ __NR_rt_sigsuspend ] = sys_rt_sigsuspend,
-	[ __NR_pread64 ] = sys_pread64,
-	[ __NR_pwrite64 ] = sys_pwrite64,
-	[ __NR_chown ] = sys_chown16,
-	[ __NR_getcwd ] = sys_getcwd,
-	[ __NR_capget ] = sys_capget,
-	[ __NR_capset ] = sys_capset,
-	[ __NR_sigaltstack ] = sys_sigaltstack,
-	[ __NR_sendfile ] = sys_sendfile,
-	[ __NR_getpmsg ] = sys_ni_syscall,
-	[ __NR_putpmsg ] = sys_ni_syscall,
-	[ __NR_vfork ] = sys_vfork,
-	[ __NR_ugetrlimit ] = sys_getrlimit,
-	[ __NR_mmap2 ] = sys_mmap2,
-	[ __NR_truncate64 ] = sys_truncate64,
-	[ __NR_ftruncate64 ] = sys_ftruncate64,
-	[ __NR_stat64 ] = sys_stat64,
-	[ __NR_lstat64 ] = sys_lstat64,
-	[ __NR_fstat64 ] = sys_fstat64,
-	[ __NR_fcntl64 ] = sys_fcntl64,
-	[ __NR_getdents64 ] = sys_getdents64,
-	[ __NR_gettid ] = sys_gettid,
-	[ __NR_readahead ] = sys_readahead,
-	[ __NR_setxattr ] = sys_ni_syscall,
-	[ __NR_lsetxattr ] = sys_ni_syscall,
-	[ __NR_fsetxattr ] = sys_ni_syscall,
-	[ __NR_getxattr ] = sys_ni_syscall,
-	[ __NR_lgetxattr ] = sys_ni_syscall,
-	[ __NR_fgetxattr ] = sys_ni_syscall,
-	[ __NR_listxattr ] = sys_ni_syscall,
-	[ __NR_llistxattr ] = sys_ni_syscall,
-	[ __NR_flistxattr ] = sys_ni_syscall,
-	[ __NR_removexattr ] = sys_ni_syscall,
-	[ __NR_lremovexattr ] = sys_ni_syscall,
-	[ __NR_fremovexattr ] = sys_ni_syscall,
-	[ __NR_tkill ] = sys_tkill,
-	[ __NR_sendfile64 ] = sys_sendfile64,
-	[ __NR_futex ] = sys_futex,
-	[ __NR_sched_setaffinity ] = sys_sched_setaffinity,
-	[ __NR_sched_getaffinity ] = sys_sched_getaffinity,
-	[ __NR_io_setup ] = sys_io_setup,
-	[ __NR_io_destroy ] = sys_io_destroy,
-	[ __NR_io_getevents ] = sys_io_getevents,
-	[ __NR_io_submit ] = sys_io_submit,
-	[ __NR_io_cancel ] = sys_io_cancel,
-	[ __NR_exit_group ] = sys_exit_group,
-	[ __NR_lookup_dcookie ] = sys_lookup_dcookie,
-	[ __NR_epoll_create ] = sys_epoll_create,
-	[ __NR_epoll_ctl ] = sys_epoll_ctl,
-	[ __NR_epoll_wait ] = sys_epoll_wait,
-        [ __NR_remap_file_pages ] = sys_remap_file_pages,
-        [ __NR_set_tid_address ] = sys_set_tid_address,
+	[ __NR_sched_get_priority_max ] (syscall_handler_t *) sys_sched_get_priority_max,
+	[ __NR_sched_get_priority_min ] (syscall_handler_t *) sys_sched_get_priority_min,
+	[ __NR_sched_rr_get_interval ] (syscall_handler_t *) sys_sched_rr_get_interval,
+	[ __NR_nanosleep ] (syscall_handler_t *) sys_nanosleep,
+	[ __NR_mremap ] (syscall_handler_t *) sys_mremap,
+	[ __NR_setresuid ] (syscall_handler_t *) sys_setresuid16,
+	[ __NR_getresuid ] (syscall_handler_t *) sys_getresuid16,
+	[ __NR_vm86 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_query_module ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_poll ] (syscall_handler_t *) sys_poll,
+	[ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL,
+	[ __NR_setresgid ] (syscall_handler_t *) sys_setresgid16,
+	[ __NR_getresgid ] (syscall_handler_t *) sys_getresgid16,
+	[ __NR_prctl ] (syscall_handler_t *) sys_prctl,
+	[ __NR_rt_sigreturn ] (syscall_handler_t *) sys_rt_sigreturn,
+	[ __NR_rt_sigaction ] (syscall_handler_t *) sys_rt_sigaction,
+	[ __NR_rt_sigprocmask ] (syscall_handler_t *) sys_rt_sigprocmask,
+	[ __NR_rt_sigpending ] (syscall_handler_t *) sys_rt_sigpending,
+	[ __NR_rt_sigtimedwait ] (syscall_handler_t *) sys_rt_sigtimedwait,
+	[ __NR_rt_sigqueueinfo ] (syscall_handler_t *) sys_rt_sigqueueinfo,
+	[ __NR_rt_sigsuspend ] (syscall_handler_t *) sys_rt_sigsuspend,
+	[ __NR_pread64 ] (syscall_handler_t *) sys_pread64,
+	[ __NR_pwrite64 ] (syscall_handler_t *) sys_pwrite64,
+	[ __NR_chown ] (syscall_handler_t *) sys_chown16,
+	[ __NR_getcwd ] (syscall_handler_t *) sys_getcwd,
+	[ __NR_capget ] (syscall_handler_t *) sys_capget,
+	[ __NR_capset ] (syscall_handler_t *) sys_capset,
+	[ __NR_sigaltstack ] (syscall_handler_t *) sys_sigaltstack,
+	[ __NR_sendfile ] (syscall_handler_t *) sys_sendfile,
+	[ __NR_getpmsg ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_putpmsg ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_vfork ] (syscall_handler_t *) sys_vfork,
+	[ __NR_ugetrlimit ] (syscall_handler_t *) sys_getrlimit,
+	[ __NR_mmap2 ] (syscall_handler_t *) sys_mmap2,
+	[ __NR_truncate64 ] (syscall_handler_t *) sys_truncate64,
+	[ __NR_ftruncate64 ] (syscall_handler_t *) sys_ftruncate64,
+	[ __NR_stat64 ] (syscall_handler_t *) sys_stat64,
+	[ __NR_lstat64 ] (syscall_handler_t *) sys_lstat64,
+	[ __NR_fstat64 ] (syscall_handler_t *) sys_fstat64,
+	[ __NR_getdents64 ] (syscall_handler_t *) sys_getdents64,
+	[ __NR_fcntl64 ] (syscall_handler_t *) sys_fcntl64,
+	[ 223 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_gettid ] (syscall_handler_t *) sys_gettid,
+	[ __NR_readahead ] (syscall_handler_t *) sys_readahead,
+	[ __NR_setxattr ] (syscall_handler_t *) sys_setxattr,
+	[ __NR_lsetxattr ] (syscall_handler_t *) sys_lsetxattr,
+	[ __NR_fsetxattr ] (syscall_handler_t *) sys_fsetxattr,
+	[ __NR_getxattr ] (syscall_handler_t *) sys_getxattr,
+	[ __NR_lgetxattr ] (syscall_handler_t *) sys_lgetxattr,
+	[ __NR_fgetxattr ] (syscall_handler_t *) sys_fgetxattr,
+	[ __NR_listxattr ] (syscall_handler_t *) sys_listxattr,
+	[ __NR_llistxattr ] (syscall_handler_t *) sys_llistxattr,
+	[ __NR_flistxattr ] (syscall_handler_t *) sys_flistxattr,
+	[ __NR_removexattr ] (syscall_handler_t *) sys_removexattr,
+	[ __NR_lremovexattr ] (syscall_handler_t *) sys_lremovexattr,
+	[ __NR_fremovexattr ] (syscall_handler_t *) sys_fremovexattr,
+	[ __NR_tkill ] (syscall_handler_t *) sys_tkill,
+	[ __NR_sendfile64 ] (syscall_handler_t *) sys_sendfile64,
+	[ __NR_futex ] (syscall_handler_t *) sys_futex,
+	[ __NR_sched_setaffinity ] (syscall_handler_t *) sys_sched_setaffinity,
+	[ __NR_sched_getaffinity ] (syscall_handler_t *) sys_sched_getaffinity,
+	[ __NR_set_thread_area ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_get_thread_area ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_io_setup ] (syscall_handler_t *) sys_io_setup,
+	[ __NR_io_destroy ] (syscall_handler_t *) sys_io_destroy,
+	[ __NR_io_getevents ] (syscall_handler_t *) sys_io_getevents,
+	[ __NR_io_submit ] (syscall_handler_t *) sys_io_submit,
+	[ __NR_io_cancel ] (syscall_handler_t *) sys_io_cancel,
+	[ __NR_fadvise64 ] (syscall_handler_t *) sys_fadvise64,
+	[ 251 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_exit_group ] (syscall_handler_t *) sys_exit_group,
+	[ __NR_lookup_dcookie ] (syscall_handler_t *) sys_lookup_dcookie,
+	[ __NR_epoll_create ] (syscall_handler_t *) sys_epoll_create,
+	[ __NR_epoll_ctl ] (syscall_handler_t *) sys_epoll_ctl,
+	[ __NR_epoll_wait ] (syscall_handler_t *) sys_epoll_wait,
+        [ __NR_remap_file_pages ] (syscall_handler_t *) sys_remap_file_pages,
+        [ __NR_set_tid_address ] (syscall_handler_t *) sys_set_tid_address,
+	[ __NR_timer_create ] (syscall_handler_t *) sys_timer_create,
+	[ __NR_timer_settime ] (syscall_handler_t *) sys_timer_settime,
+	[ __NR_timer_gettime ] (syscall_handler_t *) sys_timer_gettime,
+	[ __NR_timer_getoverrun ] (syscall_handler_t *) sys_timer_getoverrun,
+	[ __NR_timer_delete ] (syscall_handler_t *) sys_timer_delete,
+	[ __NR_clock_settime ] (syscall_handler_t *) sys_clock_settime,
+	[ __NR_clock_gettime ] (syscall_handler_t *) sys_clock_gettime,
+	[ __NR_clock_getres ] (syscall_handler_t *) sys_clock_getres,
+	[ __NR_clock_nanosleep ] (syscall_handler_t *) sys_clock_nanosleep,
+	[ __NR_statfs64 ] (syscall_handler_t *) sys_statfs64,
+	[ __NR_fstatfs64 ] (syscall_handler_t *) sys_fstatfs64,
+	[ __NR_tgkill ] (syscall_handler_t *) sys_tgkill,
+	[ __NR_utimes ] (syscall_handler_t *) sys_utimes,
+	[ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64,
+	[ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall,
 
 	ARCH_SYSCALLS
 	[ LAST_SYSCALL + 1 ... NR_syscalls ] = 
diff -Nru a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
--- a/arch/um/kernel/syscall_kern.c	2004-02-25 02:31:13 -08:00
+++ b/arch/um/kernel/syscall_kern.c	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -36,32 +36,34 @@
 
 long sys_fork(void)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-        p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
+        ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
-long sys_clone(unsigned long clone_flags, unsigned long newsp)
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       int *parent_tid, int *child_tid)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-	p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL);
+	ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
 long sys_vfork(void)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL);
+	ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
+		      NULL);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
 /* common code for old and new mmaps */
@@ -136,43 +138,12 @@
 
         error = do_pipe(fd);
         if (!error) {
-                if (copy_to_user(fildes, fd, 2*sizeof(int)))
+		if (copy_to_user(fildes, fd, sizeof(fd)))
                         error = -EFAULT;
         }
         return error;
 }
 
-int sys_sigaction(int sig, const struct old_sigaction *act,
-			 struct old_sigaction *oact)
-{
-	struct k_sigaction new_ka, old_ka;
-	int ret;
-
-	if (act) {
-		old_sigset_t mask;
-		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
-
 /*
  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  *
@@ -254,7 +225,7 @@
 		return sys_shmctl (first, second,
 				   (struct shmid_ds *) ptr);
 	default:
-		return -EINVAL;
+		return -ENOSYS;
 	}
 }
 
@@ -301,11 +272,6 @@
 	error = error ? -EFAULT : 0;
 
 	return error;
-}
-
-int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
-{
-	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
 }
 
 long execute_syscall(void *r)
diff -Nru a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
--- a/arch/um/kernel/sysrq.c	2004-06-27 00:19:28 -07:00
+++ b/arch/um/kernel/sysrq.c	2004-08-24 02:08:18 -07:00
@@ -44,6 +44,11 @@
 }
 EXPORT_SYMBOL(dump_stack);
 
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+	show_trace(sp);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -Nru a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c
--- a/arch/um/kernel/tempfile.c	2003-01-18 12:29:27 -08:00
+++ b/arch/um/kernel/tempfile.c	2004-08-24 02:08:18 -07:00
@@ -28,6 +28,7 @@
 	}
 	if((dir == NULL) || (*dir == '\0')) 
 		dir = "/tmp";
+
 	tempdir = malloc(strlen(dir) + 2);
 	if(tempdir == NULL){
 		fprintf(stderr, "Failed to malloc tempdir, "
@@ -49,7 +50,8 @@
 	else
 		*tempname = 0;
 	strcat(tempname, template);
-	if((fd = mkstemp(tempname)) < 0){
+	fd = mkstemp(tempname);
+	if(fd < 0){
 		fprintf(stderr, "open - cannot create %s: %s\n", tempname, 
 			strerror(errno));
 		return -1;
@@ -59,7 +61,8 @@
 		return -1;
 	}
 	if(out_tempname){
-		if((*out_tempname = strdup(tempname)) == NULL){
+		*out_tempname = strdup(tempname);
+		if(*out_tempname == NULL){
 			perror("strdup");
 			return -1;
 		}
diff -Nru a/arch/um/kernel/time.c b/arch/um/kernel/time.c
--- a/arch/um/kernel/time.c	2004-02-18 19:43:10 -08:00
+++ b/arch/um/kernel/time.c	2004-08-24 02:08:24 -07:00
@@ -4,24 +4,34 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <time.h>
 #include <sys/time.h>
 #include <signal.h>
 #include <errno.h>
-#include "linux/module.h"
+#include <string.h>
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "process.h"
 #include "signal_user.h"
 #include "time_user.h"
+#include "kern_constants.h"
+
+/* XXX This really needs to be declared and initialized in a kernel file since
+ * it's in <linux/time.h>
+ */
+extern struct timespec wall_to_monotonic;
 
 extern struct timeval xtime;
 
+struct timeval local_offset = { 0, 0 };
+
 void timer(void)
 {
 	gettimeofday(&xtime, NULL);
+	timeradd(&xtime, &local_offset, &xtime);
 }
 
 void set_interval(int timer_type)
@@ -66,7 +76,7 @@
 		       errno);
 }
 
-void idle_timer(void)
+void uml_idle_timer(void)
 {
 	if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
 		panic("Couldn't unset SIGVTALRM handler");
@@ -76,14 +86,60 @@
 	set_interval(ITIMER_REAL);
 }
 
+static unsigned long long get_host_hz(void)
+{
+	char mhzline[16], *end;
+	unsigned long long mhz;
+	int ret, mult, rest, len;
+
+	ret = cpu_feature("cpu MHz", mhzline,
+			  sizeof(mhzline) / sizeof(mhzline[0]));
+	if(!ret)
+		panic ("Could not get host MHZ");
+
+	mhz = strtoul(mhzline, &end, 10);
+
+	/* This business is to parse a floating point number without using
+	 * floating types.
+	 */
+
+	rest = 0;
+	mult = 0;
+	if(*end == '.'){
+		end++;
+		len = strlen(end);
+		if(len < 6)
+			mult = 6 - len;
+		else if(len > 6)
+			end[6] = '\0';
+		rest = strtoul(end, NULL, 10);
+		while(mult-- > 0)
+			rest *= 10;
+	}
+
+	return(1000000 * mhz + rest);
+}
+
+unsigned long long host_hz = 0;
+
+extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
+
 void time_init(void)
 {
+	struct timespec now;
+
+	host_hz = get_host_hz();
 	if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
 		panic("Couldn't set SIGVTALRM handler");
 	set_interval(ITIMER_VIRTUAL);
+
+	do_posix_clock_monotonic_gettime(&now);
+	wall_to_monotonic.tv_sec = -now.tv_sec;
+	wall_to_monotonic.tv_nsec = -now.tv_nsec;
 }
 
-struct timeval local_offset = { 0, 0 };
+/* Declared in linux/time.h, which can't be included here */
+extern void clock_was_set(void);
 
 void do_gettimeofday(struct timeval *tv)
 {
@@ -96,15 +152,13 @@
 	clock_was_set();
 }
 
-EXPORT_SYMBOL(do_gettimeofday);
-
 int do_settimeofday(struct timespec *tv)
 {
 	struct timeval now;
 	unsigned long flags;
 	struct timeval tv_in;
 
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+	if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC)
 		return -EINVAL;
 
 	tv_in.tv_sec = tv->tv_sec;
@@ -114,9 +168,9 @@
 	gettimeofday(&now, NULL);
 	timersub(&tv_in, &now, &local_offset);
 	time_unlock(flags);
-}
 
-EXPORT_SYMBOL(do_settimeofday);
+	return(0);
+}
 
 void idle_sleep(int secs)
 {
diff -Nru a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
--- a/arch/um/kernel/time_kern.c	2003-10-07 19:53:41 -07:00
+++ b/arch/um/kernel/time_kern.c	2004-08-24 02:08:24 -07:00
@@ -30,22 +30,60 @@
 	return(HZ);
 }
 
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+	return (unsigned long long)jiffies_64 * (1000000000 / HZ);
+}
+
 /* Changed at early boot */
 int timer_irq_inited = 0;
 
-/* missed_ticks will be modified after kernel memory has been 
- * write-protected, so this puts it in a section which will be left 
- * write-enabled.
- */
-int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS];
+static int first_tick;
+static unsigned long long prev_tsc;
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
+static long long delta;   		/* Deviation per interval */
+#endif
+
+extern unsigned long long host_hz;
 
 void timer_irq(union uml_pt_regs *regs)
 {
-	int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu];
+	unsigned long long ticks = 0;
+
+	if(!timer_irq_inited){
+		/* This is to ensure that ticks don't pile up when
+		 * the timer handler is suspended */
+		first_tick = 0;
+		return;
+	}
 
-        if(!timer_irq_inited) return;
-	missed_ticks[cpu] = 0;
-	while(ticks--) do_IRQ(TIMER_IRQ, regs);
+	if(first_tick){
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
+		unsigned long long tsc;
+		/* We've had 1 tick */
+		tsc = time_stamp();
+
+		delta += tsc - prev_tsc;
+		prev_tsc = tsc;
+
+		ticks += (delta * HZ) / host_hz;
+		delta -= (ticks * host_hz) / HZ;
+#else
+		ticks = 1;
+#endif
+	}
+	else {
+		prev_tsc = time_stamp();
+		first_tick = 1;
+	}
+
+	while(ticks > 0){
+		do_IRQ(TIMER_IRQ, regs);
+		ticks--;
+	}
 }
 
 void boot_timer_handler(int sig)
@@ -58,12 +96,15 @@
 	do_timer(&regs);
 }
 
-void um_timer(int irq, void *dev, struct pt_regs *regs)
+irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
 {
+	unsigned long flags;
+
 	do_timer(regs);
-	write_seqlock(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock, flags);
 	timer();
-	write_sequnlock(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+	return(IRQ_HANDLED);
 }
 
 long um_time(int * tloc)
@@ -81,12 +122,12 @@
 long um_stime(int * tptr)
 {
 	int value;
-	struct timeval new;
+	struct timespec new;
 
 	if (get_user(value, tptr))
                 return -EFAULT;
 	new.tv_sec = value;
-	new.tv_usec = 0;
+	new.tv_nsec = 0;
 	do_settimeofday(&new);
 	return 0;
 }
@@ -125,9 +166,11 @@
 void timer_handler(int sig, union uml_pt_regs *regs)
 {
 #ifdef CONFIG_SMP
+	local_irq_disable();
 	update_process_times(user_context(UPT_SP(regs)));
+	local_irq_enable();
 #endif
-	if(current->thread_info->cpu == 0)
+	if(current_thread->cpu == 0)
 		timer_irq(regs);
 }
 
@@ -136,6 +179,7 @@
 unsigned long time_lock(void)
 {
 	unsigned long flags;
+
 	spin_lock_irqsave(&timer_spinlock, flags);
 	return(flags);
 }
@@ -150,8 +194,8 @@
 	int err;
 
 	CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
-	if((err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", 
-			      NULL)) != 0)
+	err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
+	if(err != 0)
 		printk(KERN_ERR "timer_init : request_irq failed - "
 		       "errno = %d\n", -err);
 	timer_irq_inited = 1;
@@ -159,7 +203,6 @@
 }
 
 __initcall(timer_init);
-
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -Nru a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
--- a/arch/um/kernel/trap_kern.c	2003-02-05 07:18:58 -08:00
+++ b/arch/um/kernel/trap_kern.c	2004-08-24 02:08:29 -07:00
@@ -16,12 +16,15 @@
 #include "asm/tlbflush.h"
 #include "asm/a.out.h"
 #include "asm/current.h"
+#include "asm/irq.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
 #include "chan_kern.h"
 #include "mconsole_kern.h"
 #include "2_5compat.h"
+#include "mem.h"
+#include "mem_kern.h"
 
 int handle_page_fault(unsigned long address, unsigned long ip, 
 		      int is_write, int is_user, int *code_out)
@@ -51,12 +54,10 @@
 	if(is_write && !(vma->vm_flags & VM_WRITE)) 
 		goto out;
 	page = address & PAGE_MASK;
-	if(page == (unsigned long) current->thread_info + PAGE_SIZE)
-		panic("Kernel stack overflow");
 	pgd = pgd_offset(mm, page);
 	pmd = pmd_offset(pgd, page);
- survive:
 	do {
+ survive:
 		switch (handle_mm_fault(mm, vma, address, is_write)){
 		case VM_FAULT_MINOR:
 			current->min_flt++;
@@ -75,10 +76,10 @@
 		}
 		pte = pte_offset_kernel(pmd, page);
 	} while(!pte_present(*pte));
+	err = 0;
 	*pte = pte_mkyoung(*pte);
 	if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
 	flush_tlb_page(vma, page);
-	err = 0;
  out:
 	up_read(&mm->mmap_sem);
 	return(err);
@@ -94,10 +95,36 @@
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
-	err = -ENOMEM;
 	goto out;
 }
 
+LIST_HEAD(physmem_remappers);
+
+void register_remapper(struct remapper *info)
+{
+	list_add(&info->list, &physmem_remappers);
+}
+
+static int check_remapped_addr(unsigned long address, int is_write)
+{
+	struct remapper *remapper;
+	struct list_head *ele;
+	__u64 offset;
+	int fd;
+
+	fd = phys_mapping(__pa(address), &offset);
+	if(fd == -1)
+		return(0);
+
+	list_for_each(ele, &physmem_remappers){
+		remapper = list_entry(ele, struct remapper, list);
+		if((*remapper->proc)(fd, address, is_write, offset))
+			return(1);
+	}
+
+	return(0);
+}
+
 unsigned long segv(unsigned long address, unsigned long ip, int is_write, 
 		   int is_user, void *sc)
 {
@@ -109,7 +136,9 @@
                 flush_tlb_kernel_vm();
                 return(0);
         }
-        if(current->mm == NULL)
+	else if(check_remapped_addr(address & PAGE_MASK, is_write))
+		return(0);
+	else if(current->mm == NULL)
 		panic("Segfault with no mm");
 	err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
 
@@ -120,9 +149,8 @@
 		current->thread.fault_addr = (void *) address;
 		do_longjmp(catcher, 1);
 	} 
-	else if(current->thread.fault_addr != NULL){
+	else if(current->thread.fault_addr != NULL)
 		panic("fault_addr set but no fault catcher");
-	}
 	else if(arch_fixup(ip, sc))
 		return(0);
 
@@ -155,8 +183,6 @@
 {
 	struct siginfo si;
 
-	printk(KERN_ERR "Unfixable SEGV in '%s' (pid %d) at 0x%lx "
-	       "(ip 0x%lx)\n", current->comm, current->pid, address, ip);
 	si.si_signo = SIGSEGV;
 	si.si_code = SEGV_ACCERR;
 	si.si_addr = (void *) address;
@@ -178,6 +204,11 @@
 	if(current->thread.fault_catcher != NULL)
 		do_longjmp(current->thread.fault_catcher, 1);
 	else relay_signal(sig, regs);
+}
+
+void winch(int sig, union uml_pt_regs *regs)
+{
+	do_IRQ(WINCH_IRQ, regs);
 }
 
 void trap_init(void)
diff -Nru a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
--- a/arch/um/kernel/trap_user.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/trap_user.c	2004-08-24 02:08:27 -07:00
@@ -5,11 +5,9 @@
 
 #include <stdlib.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/time.h>
-#include <sys/ioctl.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <asm/page.h>
@@ -34,7 +32,14 @@
 {
 	kill(pid, SIGKILL);
 	kill(pid, SIGCONT);
-	while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT);
+	do {
+		int n;
+		CATCH_EINTR(n = waitpid(pid, NULL, 0));
+		if (n > 0)
+			kill(pid, SIGCONT);
+		else
+			break;
+	} while(1);
 }
 
 /* Unlocked - don't care if this is a bit off */
@@ -82,6 +87,8 @@
 		     .is_irq 		= 0 },
 	[ SIGILL ] { .handler 		= relay_signal,
 		     .is_irq 		= 0 },
+	[ SIGWINCH ] { .handler		= winch,
+		       .is_irq		= 1 },
 	[ SIGBUS ] { .handler 		= bus_handler,
 		     .is_irq 		= 0 },
 	[ SIGSEGV] { .handler 		= segv_handler,
@@ -102,12 +109,11 @@
 			 sig, &sc);
 }
 
-extern int timer_irq_inited, missed_ticks[];
+extern int timer_irq_inited;
 
 void alarm_handler(int sig, struct sigcontext sc)
 {
 	if(!timer_irq_inited) return;
-	missed_ticks[cpu()]++;
 
 	if(sig == SIGALRM)
 		switch_timers(0);
@@ -123,7 +129,7 @@
 {
 	jmp_buf *buf = b;
 
-	longjmp(*buf, val);
+	siglongjmp(*buf, val);
 }
 
 /*
diff -Nru a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
--- a/arch/um/kernel/tt/Makefile	2003-03-09 14:15:54 -08:00
+++ b/arch/um/kernel/tt/Makefile	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 # 
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
 # Licensed under the GPL
 #
 
@@ -7,7 +7,7 @@
 
 obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
 	syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
-	uaccess_user.o sys-$(SUBARCH)/
+	uaccess.o uaccess_user.o sys-$(SUBARCH)/
 
 obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
 
@@ -27,5 +27,3 @@
 
 $(obj)/unmap_fin.o : $(src)/unmap.o
 	ld -r -o $@ $< -lc -L/usr/lib
-
-clean :
diff -Nru a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
--- a/arch/um/kernel/tt/exec_kern.c	2002-11-23 13:49:53 -08:00
+++ b/arch/um/kernel/tt/exec_kern.c	2004-08-24 02:08:18 -07:00
@@ -17,6 +17,7 @@
 #include "mem_user.h"
 #include "os.h"
 #include "tlb.h"
+#include "mode.h"
 
 static int exec_tramp(void *sig_stack)
 {
@@ -47,17 +48,17 @@
 		do_exit(SIGKILL);
 	}
 
-	if(current->thread_info->cpu == 0)
+	if(current_thread->cpu == 0)
 		forward_interrupts(new_pid);
 	current->thread.request.op = OP_EXEC;
 	current->thread.request.u.exec.pid = new_pid;
-	unprotect_stack((unsigned long) current->thread_info);
+	unprotect_stack((unsigned long) current_thread);
 	os_usr1_process(os_getpid());
 
 	enable_timer();
 	free_page(stack);
 	protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
-	task_protections((unsigned long) current->thread_info);
+	task_protections((unsigned long) current_thread);
 	force_flush_all();
 	unblock_signals();
 }
diff -Nru a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c
--- a/arch/um/kernel/tt/exec_user.c	2002-11-19 11:39:52 -08:00
+++ b/arch/um/kernel/tt/exec_user.c	2004-08-24 02:08:27 -07:00
@@ -19,11 +19,16 @@
 void do_exec(int old_pid, int new_pid)
 {
 	unsigned long regs[FRAME_SIZE];
+	int err;
 
 	if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) ||
-	   (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0) ||
-	   (waitpid(new_pid, 0, WUNTRACED) < 0))
+	   (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0))
 		tracer_panic("do_exec failed to attach proc - errno = %d",
+			     errno);
+
+	CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED));
+	if (err < 0)
+		tracer_panic("do_exec failed to attach proc in waitpid - errno = %d",
 			     errno);
 
 	if(ptrace_getregs(old_pid, regs) < 0)
diff -Nru a/arch/um/kernel/tt/include/mode.h b/arch/um/kernel/tt/include/mode.h
--- a/arch/um/kernel/tt/include/mode.h	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/tt/include/mode.h	2004-08-24 02:08:18 -07:00
@@ -8,6 +8,8 @@
 
 #include "sysdep/ptrace.h"
 
+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
+
 extern int tracing_pid;
 
 extern int tracer(int (*init_proc)(void *), void *sp);
diff -Nru a/arch/um/kernel/tt/include/uaccess.h b/arch/um/kernel/tt/include/uaccess.h
--- a/arch/um/kernel/tt/include/uaccess.h	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/tt/include/uaccess.h	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -43,65 +43,19 @@
 
 extern int __do_copy_from_user(void *to, const void *from, int n,
 			       void **fault_addr, void **fault_catcher);
-
-static inline int copy_from_user_tt(void *to, const void *from, int n)
-{
-	return(access_ok_tt(VERIFY_READ, from, n) ?
-	       __do_copy_from_user(to, from, n, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher) : n);
-}
-
-static inline int copy_to_user_tt(void *to, const void *from, int n)
-{
-	return(access_ok_tt(VERIFY_WRITE, to, n) ?
-	       __do_copy_to_user(to, from, n, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher) : n);
-}
-
 extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
 				  void **fault_addr, void **fault_catcher);
-
-static inline int strncpy_from_user_tt(char *dst, const char *src, int count)
-{
-	int n;
-
-	if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT);
-	n = __do_strncpy_from_user(dst, src, count, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher);
-	if(n < 0) return(-EFAULT);
-	return(n);
-}
-
 extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
 			   void **fault_catcher);
-
-static inline int __clear_user_tt(void *mem, int len)
-{
-	return(__do_clear_user(mem, len,
-			       &current->thread.fault_addr,
-			       &current->thread.fault_catcher));
-}
-
-static inline int clear_user_tt(void *mem, int len)
-{
-	return(access_ok_tt(VERIFY_WRITE, mem, len) ? 
-	       __do_clear_user(mem, len, 
-			       &current->thread.fault_addr,
-			       &current->thread.fault_catcher) : len);
-}
-
 extern int __do_strnlen_user(const char *str, unsigned long n,
 			     void **fault_addr, void **fault_catcher);
 
-static inline int strnlen_user_tt(const void *str, int len)
-{
-	return(__do_strnlen_user(str, len,
-				 &current->thread.fault_addr,
-				 &current->thread.fault_catcher));
-}
+extern int copy_from_user_tt(void *to, const void *from, int n);
+extern int copy_to_user_tt(void *to, const void *from, int n);
+extern int strncpy_from_user_tt(char *dst, const char *src, int count);
+extern int __clear_user_tt(void *mem, int len);
+extern int clear_user_tt(void *mem, int len);
+extern int strnlen_user_tt(const void *str, int len);
 
 #endif
 
diff -Nru a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
--- a/arch/um/kernel/tt/mem.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/tt/mem.c	2004-08-24 02:08:29 -07:00
@@ -18,7 +18,7 @@
 	if(!jail || debug)
 		remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
 	remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
-	remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(brk_start), 1);
+	remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
 }
 
 #ifdef CONFIG_HOST_2G_2G
diff -Nru a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c
--- a/arch/um/kernel/tt/mem_user.c	2003-01-17 19:19:56 -08:00
+++ b/arch/um/kernel/tt/mem_user.c	2004-08-24 02:08:18 -07:00
@@ -25,14 +25,13 @@
 	size = (unsigned long) segment_end - 
 		(unsigned long) segment_start;
 	data = create_mem_file(size);
-	if((addr = mmap(NULL, size, PROT_WRITE | PROT_READ, 
-			MAP_SHARED, data, 0)) == MAP_FAILED){
+	addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0);
+	if(addr == MAP_FAILED){
 		perror("mapping new data segment");
 		exit(1);
 	}
 	memcpy(addr, segment_start, size);
-	if(switcheroo(data, prot, addr, segment_start, 
-		      size) < 0){
+	if(switcheroo(data, prot, addr, segment_start, size) < 0){
 		printf("switcheroo failed\n");
 		exit(1);
 	}
diff -Nru a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
--- a/arch/um/kernel/tt/process_kern.c	2003-08-18 19:46:23 -07:00
+++ b/arch/um/kernel/tt/process_kern.c	2004-08-24 02:08:29 -07:00
@@ -62,7 +62,7 @@
 	reading = 0;
 	err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
 	if(err != sizeof(c))
-		panic("write of switch_pipe failed, errno = %d", -err);
+		panic("write of switch_pipe failed, err = %d", -err);
 
 	reading = 1;
 	if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD))
@@ -104,48 +104,72 @@
 
 void release_thread_tt(struct task_struct *task)
 {
-	os_kill_process(task->thread.mode.tt.extern_pid, 0);
+	int pid = task->thread.mode.tt.extern_pid;
+
+	if(os_getpid() != pid)
+		os_kill_process(pid, 0);
 }
 
 void exit_thread_tt(void)
 {
-	close(current->thread.mode.tt.switch_pipe[0]);
-	close(current->thread.mode.tt.switch_pipe[1]);
+	os_close_file(current->thread.mode.tt.switch_pipe[0]);
+	os_close_file(current->thread.mode.tt.switch_pipe[1]);
 }
 
 void schedule_tail(task_t *prev);
 
 static void new_thread_handler(int sig)
 {
+	unsigned long disable;
 	int (*fn)(void *);
 	void *arg;
 
 	fn = current->thread.request.u.thread.proc;
 	arg = current->thread.request.u.thread.arg;
+
 	UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
+	disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
+		(1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
+	SC_SIGMASK(UPT_SC(&current->thread.regs.regs)) &= ~disable;
+
 	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 
-	block_signals();
+	force_flush_all();
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
+	current->thread.prev_sched = NULL;
+
 	init_new_thread_signals(1);
-#ifdef CONFIG_SMP
-	schedule_tail(current->thread.prev_sched);
-#endif
 	enable_timer();
 	free_page(current->thread.temp_stack);
 	set_cmdline("(kernel thread)");
-	force_flush_all();
 
-	current->thread.prev_sched = NULL;
 	change_sig(SIGUSR1, 1);
 	change_sig(SIGVTALRM, 1);
 	change_sig(SIGPROF, 1);
-	unblock_signals();
+	local_irq_enable();
 	if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
 		do_exit(0);
 }
 
 static int new_thread_proc(void *stack)
 {
+	/* local_irq_disable is needed to block out signals until this thread is
+	 * properly scheduled.  Otherwise, the tracing thread will get mighty
+	 * upset about any signals that arrive before that.
+	 * This has the complication that it sets the saved signal mask in
+	 * the sigcontext to block signals.  This gets restored when this
+	 * thread (or a descendant, since they get a copy of this sigcontext)
+	 * returns to userspace.
+	 * So, this is compensated for elsewhere.
+	 * XXX There is still a small window until local_irq_disable() actually
+	 * finishes where signals are possible - shouldn't be a problem in
+	 * practice since SIGIO hasn't been forwarded here yet, and the
+	 * local_irq_disable should finish before a SIGVTALRM has time to be
+	 * delivered.
+	 */
+
+	local_irq_disable();
 	init_new_thread_stack(stack, new_thread_handler);
 	os_usr1_process(os_getpid());
 	return(0);
@@ -156,7 +180,7 @@
  * itself with a SIGUSR1.  set_user_mode has to be run with SIGUSR1 off,
  * so it is blocked before it's called.  They are re-enabled on sigreturn
  * despite the fact that they were blocked when the SIGUSR1 was issued because
- * copy_thread copies the parent's signcontext, including the signal mask
+ * copy_thread copies the parent's sigcontext, including the signal mask
  * onto the signal frame.
  */
 
@@ -165,35 +189,32 @@
  	UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
 	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 
-#ifdef CONFIG_SMP	
-	schedule_tail(NULL);
-#endif
+	force_flush_all();
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
+	current->thread.prev_sched = NULL;
+
 	enable_timer();
 	change_sig(SIGVTALRM, 1);
 	local_irq_enable();
-	force_flush_all();
 	if(current->mm != current->parent->mm)
 		protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 
 			       1, 0, 1);
-	task_protections((unsigned long) current->thread_info);
-
-	current->thread.prev_sched = NULL;
+	task_protections((unsigned long) current_thread);
 
 	free_page(current->thread.temp_stack);
+	local_irq_disable();
 	change_sig(SIGUSR1, 0);
 	set_user_mode(current);
 }
 
-static int sigusr1 = SIGUSR1;
-
 int fork_tramp(void *stack)
 {
-	int sig = sigusr1;
-
 	local_irq_disable();
+	arch_init_thread();
 	init_new_thread_stack(stack, finish_fork_handler);
 
-	kill(os_getpid(), sig);
+	os_usr1_process(os_getpid());
 	return(0);
 }
 
@@ -213,8 +234,8 @@
 	}
 
 	err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
-	if(err){
-		printk("copy_thread : pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("copy_thread : pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -377,8 +398,8 @@
 
 	pages = (1 << CONFIG_KERNEL_STACK_ORDER);
 
-	start = (unsigned long) current->thread_info + PAGE_SIZE;
-	end = (unsigned long) current + PAGE_SIZE * pages;
+	start = (unsigned long) current_thread + PAGE_SIZE;
+	end = (unsigned long) current_thread + PAGE_SIZE * pages;
 	protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
 	protect_memory(end, high_physmem - end, 1, w, 1, 1);
 
@@ -391,7 +412,7 @@
 	protect_memory(start, end - start, 1, w, 1, 1);
 
 	start = (unsigned long) UML_ROUND_DOWN(&__bss_start);
-	end = (unsigned long) UML_ROUND_UP(brk_start);
+	end = (unsigned long) UML_ROUND_UP(&_end);
 	protect_memory(start, end - start, 1, w, 1, 1);
 
 	mprotect_kernel_vm(w);
@@ -454,8 +475,9 @@
 
 	init_task.thread.mode.tt.extern_pid = pid;
 	err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
-	if(err)	panic("Can't create switch pipe for init_task, errno = %d", 
-		      err);
+	if(err)
+		panic("Can't create switch pipe for init_task, errno = %d",
+		      -err);
 }
 
 int singlestepping_tt(void *t)
diff -Nru a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile
--- a/arch/um/kernel/tt/ptproxy/Makefile	2002-12-16 23:54:52 -08:00
+++ b/arch/um/kernel/tt/ptproxy/Makefile	2004-08-24 02:08:18 -07:00
@@ -9,5 +9,3 @@
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
diff -Nru a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
--- a/arch/um/kernel/tt/ptproxy/proxy.c	2002-12-28 16:48:34 -08:00
+++ b/arch/um/kernel/tt/ptproxy/proxy.c	2004-08-24 02:08:27 -07:00
@@ -15,7 +15,6 @@
 #include <unistd.h>
 #include <signal.h>
 #include <string.h>
-#include <fcntl.h>
 #include <termios.h>
 #include <sys/wait.h>
 #include <sys/types.h>
@@ -273,7 +272,7 @@
 
 	child_proxy(1, W_EXITCODE(0, 0));
 	while(debugger.waiting == 1){
-		pid = waitpid(debugger.pid, &status, WUNTRACED);
+		CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
 		if(pid != debugger.pid){
 			printk("fake_child_exit - waitpid failed, "
 			       "errno = %d\n", errno);
@@ -281,7 +280,7 @@
 		}
 		debugger_proxy(status, debugger.pid);
 	}
-	pid = waitpid(debugger.pid, &status, WUNTRACED);
+	CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
 	if(pid != debugger.pid){
 		printk("fake_child_exit - waitpid failed, "
 		       "errno = %d\n", errno);
@@ -293,10 +292,10 @@
 }
 
 char gdb_init_string[] = 
-"att 1
-b panic
-b stop
-handle SIGWINCH nostop noprint pass
+"att 1 \n\
+b panic \n\
+b stop \n\
+handle SIGWINCH nostop noprint pass \n\
 ";
 
 int start_debugger(char *prog, int startup, int stop, int *fd_out)
@@ -304,7 +303,8 @@
 	int slave, child;
 
 	slave = open_gdb_chan();
-	if((child = fork()) == 0){
+	child = fork();
+	if(child == 0){
 		char *tempname = NULL;
 		int fd;
 
@@ -327,18 +327,19 @@
 			exit(1);
 #endif
 		}
-		if((fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0)) < 0){
-			printk("start_debugger : make_tempfile failed, errno = %d\n",
-			       errno);
+		fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
+		if(fd < 0){
+			printk("start_debugger : make_tempfile failed,"
+			       "err = %d\n", -fd);
 			exit(1);
 		}
-		write(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
+		os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
 		if(startup){
 			if(stop){
-				write(fd, "b start_kernel\n",
+				os_write_file(fd, "b start_kernel\n",
 				      strlen("b start_kernel\n"));
 			}
-			write(fd, "c\n", strlen("c\n"));
+			os_write_file(fd, "c\n", strlen("c\n"));
 		}
 		if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
 			printk("start_debugger :  PTRACE_TRACEME failed, "
diff -Nru a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
--- a/arch/um/kernel/tt/ptproxy/sysdep.c	2002-11-18 19:33:22 -08:00
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c	2004-08-24 02:08:18 -07:00
@@ -9,6 +9,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <asm/ptrace.h>
diff -Nru a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
--- a/arch/um/kernel/tt/ptproxy/wait.c	2002-11-18 19:33:22 -08:00
+++ b/arch/um/kernel/tt/ptproxy/wait.c	2004-08-24 02:08:18 -07:00
@@ -56,21 +56,23 @@
 int real_wait_return(struct debugger *debugger)
 {
 	unsigned long ip;
-	int err, pid;
+	int pid;
 
 	pid = debugger->pid;
+
 	ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
-	ip = IP_RESTART_SYSCALL(ip);
-	err = ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip);
+	IP_RESTART_SYSCALL(ip);
+
 	if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0)
 		tracer_panic("real_wait_return : Failed to restart system "
-			     "call, errno = %d\n");
+			     "call, errno = %d\n", errno);
+
 	if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
 	   (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
 	   (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
 	   debugger_normal_return(debugger, -1))
 		tracer_panic("real_wait_return : gdb failed to wait, "
-			     "errno = %d\n");
+			     "errno = %d\n", errno);
 	return(0);
 }
 
diff -Nru a/arch/um/kernel/tt/sys-i386/Makefile b/arch/um/kernel/tt/sys-i386/Makefile
--- a/arch/um/kernel/tt/sys-i386/Makefile	2002-12-16 23:21:40 -08:00
+++ b/arch/um/kernel/tt/sys-i386/Makefile	2004-08-24 02:08:18 -07:00
@@ -10,5 +10,3 @@
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
diff -Nru a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
--- a/arch/um/kernel/tt/syscall_kern.c	2003-02-15 19:30:17 -08:00
+++ b/arch/um/kernel/tt/syscall_kern.c	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
diff -Nru a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
--- a/arch/um/kernel/tt/syscall_user.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/tt/syscall_user.c	2004-08-24 02:08:18 -07:00
@@ -33,7 +33,7 @@
 	SC_START_SYSCALL(sc);
 
 	index = record_syscall_start(syscall);
-	syscall_trace();
+	syscall_trace(regs, 1);
 	result = execute_syscall(regs);
 
 	/* regs->sc may have changed while the system call ran (there may
@@ -46,7 +46,7 @@
 	   (result == -ERESTARTNOINTR))
 		do_signal(result);
 
-	syscall_trace();
+	syscall_trace(regs, 0);
 	record_syscall_end(index, result);
 }
 
diff -Nru a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
--- a/arch/um/kernel/tt/tlb.c	2002-12-29 12:05:51 -08:00
+++ b/arch/um/kernel/tt/tlb.c	2004-08-24 02:08:18 -07:00
@@ -10,6 +10,7 @@
 #include "asm/page.h"
 #include "asm/pgtable.h"
 #include "asm/uaccess.h"
+#include "asm/tlbflush.h"
 #include "user_util.h"
 #include "mem_user.h"
 #include "os.h"
diff -Nru a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
--- a/arch/um/kernel/tt/tracer.c	2002-12-29 16:18:43 -08:00
+++ b/arch/um/kernel/tt/tracer.c	2004-08-24 02:08:27 -07:00
@@ -39,16 +39,17 @@
 		return(0);
 
 	register_winch_irq(tracer_winch[0], fd, -1, data);
-	return(0);
+	return(1);
 }
 
 static void tracer_winch_handler(int sig)
 {
+	int n;
 	char c = 1;
 
-	if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c))
-		printk("tracer_winch_handler - write failed, errno = %d\n",
-		       errno);
+	n = os_write_file(tracer_winch[1], &c, sizeof(c));
+	if(n != sizeof(c))
+		printk("tracer_winch_handler - write failed, err = %d\n", -n);
 }
 
 /* Called only by the tracing thread during initialization */
@@ -58,9 +59,8 @@
 	int err;
 
 	err = os_pipe(tracer_winch, 1, 1);
-	if(err){
-		printk("setup_tracer_winch : os_pipe failed, errno = %d\n", 
-		       -err);
+	if(err < 0){
+		printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
 		return;
 	}
 	signal(SIGWINCH, tracer_winch_handler);
@@ -130,8 +130,8 @@
 	case SIGTSTP:
 		if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
 			tracer_panic("sleeping_process_signal : Failed to "
-				     "continue pid %d, errno = %d\n", pid,
-				     sig);
+				     "continue pid %d, signal = %d, "
+				     "errno = %d\n", pid, sig, errno);
 		break;
 
 	/* This happens when the debugger (e.g. strace) is doing system call 
@@ -145,7 +145,7 @@
 		if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
 			tracer_panic("sleeping_process_signal : Failed to "
 				     "PTRACE_SYSCALL pid %d, errno = %d\n",
-				     pid, sig);
+				     pid, errno);
 		break;
 	case SIGSTOP:
 		break;
@@ -192,7 +192,7 @@
 	printf("tracing thread pid = %d\n", tracing_pid);
 
 	pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
-	n = waitpid(pid, &status, WUNTRACED);
+	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0){
 		printf("waitpid on idle thread failed, errno = %d\n", errno);
 		exit(1);
@@ -218,7 +218,7 @@
 			err = attach(debugger_parent);
 			if(err){
 				printf("Failed to attach debugger parent %d, "
-				       "errno = %d\n", debugger_parent, err);
+				       "errno = %d\n", debugger_parent, -err);
 				debugger_parent = -1;
 			}
 			else {
@@ -233,7 +233,8 @@
 	}
 	set_cmdline("(tracing thread)");
 	while(1){
-		if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){
+		CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED));
+		if(pid <= 0){
 			if(errno != ECHILD){
 				printf("wait failed - errno = %d\n", errno);
 			}
@@ -401,7 +402,7 @@
 		
 		if(!strcmp(line, "go"))	debug_stop = 0;
 		else if(!strcmp(line, "parent")) debug_parent = 1;
-		else printk("Unknown debug option : '%s'\n", line);
+		else printf("Unknown debug option : '%s'\n", line);
 
 		line = next;
 	}
diff -Nru a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/kernel/tt/uaccess.c	2004-08-24 11:13:14 -07:00
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "asm/uaccess.h"
+
+int copy_from_user_tt(void *to, const void *from, int n)
+{
+	if(!access_ok_tt(VERIFY_READ, from, n))
+		return(n);
+
+	return(__do_copy_from_user(to, from, n, &current->thread.fault_addr,
+				   &current->thread.fault_catcher));
+}
+
+int copy_to_user_tt(void *to, const void *from, int n)
+{
+	if(!access_ok_tt(VERIFY_WRITE, to, n))
+		return(n);
+
+	return(__do_copy_to_user(to, from, n, &current->thread.fault_addr,
+				 &current->thread.fault_catcher));
+}
+
+int strncpy_from_user_tt(char *dst, const char *src, int count)
+{
+	int n;
+
+	if(!access_ok_tt(VERIFY_READ, src, 1))
+		return(-EFAULT);
+
+	n = __do_strncpy_from_user(dst, src, count,
+				   &current->thread.fault_addr,
+				   &current->thread.fault_catcher);
+	if(n < 0) return(-EFAULT);
+	return(n);
+}
+
+int __clear_user_tt(void *mem, int len)
+{
+	return(__do_clear_user(mem, len,
+			       &current->thread.fault_addr,
+			       &current->thread.fault_catcher));
+}
+
+int clear_user_tt(void *mem, int len)
+{
+	if(!access_ok_tt(VERIFY_WRITE, mem, len))
+		return(len);
+
+	return(__do_clear_user(mem, len, &current->thread.fault_addr,
+			       &current->thread.fault_catcher));
+}
+
+int strnlen_user_tt(const void *str, int len)
+{
+	return(__do_strnlen_user(str, len,
+				 &current->thread.fault_addr,
+				 &current->thread.fault_catcher));
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
--- a/arch/um/kernel/tt/uaccess_user.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/kernel/tt/uaccess_user.c	2004-08-24 02:08:18 -07:00
@@ -8,15 +8,20 @@
 #include <string.h>
 #include "user_util.h"
 #include "uml_uaccess.h"
+#include "task.h"
+#include "kern_util.h"
 
 int __do_copy_from_user(void *to, const void *from, int n,
 			void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
 			       __do_copy, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(0);
 	else return(n - (fault - (unsigned long) from));
 }
@@ -29,11 +34,14 @@
 int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
 			   void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
 			       __do_strncpy, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(strlen(dst));
 	else return(-1);
 }
@@ -46,11 +54,14 @@
 int __do_clear_user(void *mem, unsigned long len,
 		    void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
 			       __do_clear, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(0);
 	else return(len - (fault - (unsigned long) mem));
 }
@@ -58,19 +69,20 @@
 int __do_strnlen_user(const char *str, unsigned long n,
 		      void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	int ret;
 	unsigned long *faddrp = (unsigned long *)fault_addr;
 	jmp_buf jbuf;
 
 	*fault_catcher = &jbuf;
-	if(setjmp(jbuf) == 0){
+	if(sigsetjmp(jbuf, 1) == 0)
 		ret = strlen(str) + 1;
-	} 
-	else {
-		ret = *faddrp - (unsigned long) str;
-	}
+	else ret = *faddrp - (unsigned long) str;
+
 	*fault_addr = NULL;
 	*fault_catcher = NULL;
+
+	TASK_REGS(get_current())->tt = save;
 	return ret;
 }
 
diff -Nru a/arch/um/kernel/tt/unmap.c b/arch/um/kernel/tt/unmap.c
--- a/arch/um/kernel/tt/unmap.c	2002-12-29 09:03:35 -08:00
+++ b/arch/um/kernel/tt/unmap.c	2004-08-24 02:08:18 -07:00
@@ -3,10 +3,7 @@
  * Licensed under the GPL
  */
 
-#include <stdio.h>
-#include <errno.h>
 #include <sys/mman.h>
-#include "user.h"
 
 int switcheroo(int fd, int prot, void *from, void *to, int size)
 {
diff -Nru a/arch/um/kernel/tty_log.c b/arch/um/kernel/tty_log.c
--- a/arch/um/kernel/tty_log.c	2002-11-18 18:53:14 -08:00
+++ b/arch/um/kernel/tty_log.c	2004-08-24 02:08:18 -07:00
@@ -9,10 +9,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <sys/time.h>
 #include "init.h"
 #include "user.h"
+#include "kern_util.h"
 #include "os.h"
 
 #define TTY_LOG_DIR "./"
@@ -24,29 +24,40 @@
 #define TTY_LOG_OPEN 1
 #define TTY_LOG_CLOSE 2
 #define TTY_LOG_WRITE 3
+#define TTY_LOG_EXEC 4
+
+#define TTY_READ 1
+#define TTY_WRITE 2
 
 struct tty_log_buf {
 	int what;
 	unsigned long tty;
 	int len;
+	int direction;
+	unsigned long sec;
+	unsigned long usec;
 };
 
-int open_tty_log(void *tty)
+int open_tty_log(void *tty, void *current_tty)
 {
 	struct timeval tv;
 	struct tty_log_buf data;
 	char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
 	int fd;
 
+	gettimeofday(&tv, NULL);
 	if(tty_log_fd != -1){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_OPEN,
-					       tty : (unsigned long) tty,
-					       len : 0 });
-		write(tty_log_fd, &data, sizeof(data));
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_OPEN,
+					       .tty  = (unsigned long) tty,
+					       .len  = sizeof(current_tty),
+					       .direction = 0,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
+		os_write_file(tty_log_fd, &current_tty, data.len);
 		return(tty_log_fd);
 	}
 
-	gettimeofday(&tv, NULL);
 	sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, 
  		(unsigned int) tv.tv_usec);
 
@@ -62,30 +73,117 @@
 void close_tty_log(int fd, void *tty)
 {
 	struct tty_log_buf data;
+	struct timeval tv;
 
 	if(tty_log_fd != -1){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_CLOSE,
-					       tty : (unsigned long) tty,
-					       len : 0 });
-		write(tty_log_fd, &data, sizeof(data));
+		gettimeofday(&tv, NULL);
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_CLOSE,
+					       .tty  = (unsigned long) tty,
+					       .len  = 0,
+					       .direction = 0,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
 		return;
 	}
-	close(fd);
+	os_close_file(fd);
 }
 
-int write_tty_log(int fd, char *buf, int len, void *tty)
+static int log_chunk(int fd, const char *buf, int len)
 {
+	int total = 0, try, missed, n;
+	char chunk[64];
+
+	while(len > 0){
+		try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
+		missed = copy_from_user_proc(chunk, (char *) buf, try);
+		try -= missed;
+		n = os_write_file(fd, chunk, try);
+		if(n != try) {
+			if(n < 0)
+				return(n);
+			return(-EIO);
+		}
+		if(missed != 0)
+			return(-EFAULT);
+
+		len -= try;
+		total += try;
+		buf += try;
+	}
+
+	return(total);
+}
+
+int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
+{
+	struct timeval tv;
 	struct tty_log_buf data;
+	int direction;
 
 	if(fd == tty_log_fd){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_WRITE,
-					       tty : (unsigned long) tty,
-					       len : len });
-		write(tty_log_fd, &data, sizeof(data));
+		gettimeofday(&tv, NULL);
+		direction = is_read ? TTY_READ : TTY_WRITE;
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_WRITE,
+					       .tty  = (unsigned long) tty,
+					       .len  = len,
+					       .direction = direction,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
+	}
+
+	return(log_chunk(fd, buf, len));
+}
+
+void log_exec(char **argv, void *tty)
+{
+	struct timeval tv;
+	struct tty_log_buf data;
+	char **ptr,*arg;
+	int len;
+
+	if(tty_log_fd == -1) return;
+
+	gettimeofday(&tv, NULL);
+
+	len = 0;
+	for(ptr = argv; ; ptr++){
+		if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
+			return;
+		if(arg == NULL) break;
+		len += strlen_user_proc(arg);
+	}
+
+	data = ((struct tty_log_buf) { .what 	= TTY_LOG_EXEC,
+				       .tty  = (unsigned long) tty,
+				       .len  = len,
+				       .direction = 0,
+				       .sec = tv.tv_sec,
+				       .usec = tv.tv_usec } );
+	os_write_file(tty_log_fd, &data, sizeof(data));
+
+	for(ptr = argv; ; ptr++){
+		if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
+			return;
+		if(arg == NULL) break;
+		log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
 	}
-	return(write(fd, buf, len));
 }
 
+extern void register_tty_logger(int (*opener)(void *, void *),
+				int (*writer)(int, const char *, int,
+					      void *, int),
+				void (*closer)(int, void *));
+
+static int register_logger(void)
+{
+	register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
+	return(0);
+}
+
+__uml_initcall(register_logger);
+
 static int __init set_tty_log_dir(char *name, int *add)
 {
 	tty_log_dir = name;
@@ -104,7 +202,7 @@
 
 	tty_log_fd = strtoul(name, &end, 0);
 	if((*end != '\0') || (end == name)){
-		printk("set_tty_log_fd - strtoul failed on '%s'\n", name);
+		printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
 		tty_log_fd = -1;
 	}
 	return 0;
diff -Nru a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c
--- a/arch/um/kernel/uaccess_user.c	2002-12-29 17:05:48 -08:00
+++ b/arch/um/kernel/uaccess_user.c	2004-08-24 02:08:18 -07:00
@@ -20,7 +20,7 @@
 
 	jmp_buf jbuf;
 	*fault_catcher = &jbuf;
-	if(setjmp(jbuf) == 0){
+	if(sigsetjmp(jbuf, 1) == 0){
 		(*op)(to, from, n);
 		ret = 0;
 		*faulted_out = 0;
diff -Nru a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
--- a/arch/um/kernel/um_arch.c	2004-02-03 21:36:27 -08:00
+++ b/arch/um/kernel/um_arch.c	2004-08-24 02:08:18 -07:00
@@ -38,13 +38,18 @@
 #include "mode_kern.h"
 #include "mode.h"
 
-#define DEFAULT_COMMAND_LINE "root=6200"
+#define DEFAULT_COMMAND_LINE "root=98:0"
 
 struct cpuinfo_um boot_cpu_data = { 
 	.loops_per_jiffy	= 0,
 	.ipi_pipe		= { -1, -1 }
 };
 
+/* Placeholder to make UML link until the vsyscall stuff is actually
+ * implemented
+ */
+void *__kernel_vsyscall;
+
 unsigned long thread_saved_pc(struct task_struct *task)
 {
 	return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
@@ -53,18 +58,22 @@
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-	int index;
+	int index = 0;
 
-	index = (struct cpuinfo_um *)v - cpu_data;
 #ifdef CONFIG_SMP
+	index = (struct cpuinfo_um *) v - cpu_data;
 	if (!cpu_online(index))
 		return 0;
 #endif
 
-	seq_printf(m, "bogomips\t: %lu.%02lu\n",
+	seq_printf(m, "processor\t: %d\n", index);
+	seq_printf(m, "vendor_id\t: User Mode Linux\n");
+	seq_printf(m, "model name\t: UML\n");
+	seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
+	seq_printf(m, "host\t\t: %s\n", host_info);
+	seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
 		   loops_per_jiffy/(500000/HZ),
 		   (loops_per_jiffy/(5000/HZ)) % 100);
-	seq_printf(m, "host\t\t: %s\n", host_info);
 
 	return(0);
 }
@@ -134,12 +143,12 @@
 	if(umid != NULL){
 		snprintf(argv1_begin, 
 			 (argv1_end - argv1_begin) * sizeof(*ptr), 
-			 "(%s)", umid);
+			 "(%s) ", umid);
 		ptr = &argv1_begin[strlen(argv1_begin)];
 	}
 	else ptr = argv1_begin;
 
-	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), " [%s]", cmd);
+	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
 	memset(argv1_begin + strlen(argv1_begin), '\0', 
 	       argv1_end - argv1_begin - strlen(argv1_begin));
 #endif
@@ -179,7 +188,7 @@
 static int __init uml_ncpus_setup(char *line, int *add)
 {
        if (!sscanf(line, "%d", &ncpus)) {
-               printk("Couldn't parse [%s]\n", line);
+               printf("Couldn't parse [%s]\n", line);
                return -1;
        }
 
@@ -210,7 +219,7 @@
 
 static int __init mode_tt_setup(char *line, int *add)
 {
-	printk("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
+	printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
 	return(0);
 }
 
@@ -221,7 +230,7 @@
 
 static int __init mode_tt_setup(char *line, int *add)
 {
-	printk("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
+	printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
 	return(0);
 }
 
@@ -291,7 +300,7 @@
 
 /* Set during early boot */
 unsigned long brk_start;
-static struct vm_reserved kernel_vm_reserved;
+unsigned long end_iomem;
 
 #define MIN_VMALLOC (32 * 1024 * 1024)
 
@@ -299,7 +308,7 @@
 {
 	unsigned long avail;
 	unsigned long virtmem_size, max_physmem;
-	unsigned int i, add, err;
+	unsigned int i, add;
 
 	for (i = 1; i < argc; i++){
 		if((i == 1) && (argv[i][0] == ' ')) continue;
@@ -328,12 +337,16 @@
 	argv1_end = &argv[1][strlen(argv[1])];
 #endif
   
-	set_usable_vm(uml_physmem, get_kmem_end());
-
 	highmem = 0;
-	max_physmem = get_kmem_end() - uml_physmem - MIN_VMALLOC;
-	if(physmem_size > max_physmem){
-		highmem = physmem_size - max_physmem;
+	iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
+	max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
+
+	/* Zones have to begin on a 1 << MAX_ORDER page boundary,
+	 * so this makes sure that's true for highmem
+	 */
+	max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
+	if(physmem_size + iomem_size > max_physmem){
+		highmem = physmem_size + iomem_size - max_physmem;
 		physmem_size -= highmem;
 #ifndef CONFIG_HIGHMEM
 		highmem = 0;
@@ -343,11 +356,19 @@
 	}
 
 	high_physmem = uml_physmem + physmem_size;
-	high_memory = (void *) high_physmem;
+	end_iomem = high_physmem + iomem_size;
+	high_memory = (void *) end_iomem;
 
 	start_vm = VMALLOC_START;
 
-	setup_physmem(uml_physmem, uml_reserved, physmem_size);
+	setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
+	if(init_maps(physmem_size, iomem_size, highmem)){
+		printf("Failed to allocate mem_map for %ld bytes of physical "
+		       "memory and %ld bytes of highmem\n", physmem_size,
+		       highmem);
+		exit(1);
+	}
+
 	virtmem_size = physmem_size;
 	avail = get_kmem_end() - start_vm;
 	if(physmem_size > avail) virtmem_size = avail;
@@ -357,28 +378,26 @@
 		printf("Kernel virtual memory size shrunk to %ld bytes\n",
 		       virtmem_size);
 
-	err = reserve_vm(high_physmem, end_vm, &kernel_vm_reserved);
-	if(err){
-		printf("Failed to reserve VM area for kernel VM\n");
-		exit(1);
-	}
-
   	uml_postsetup();
 
 	init_task.thread.kernel_stack = (unsigned long) &init_thread_info + 
 		2 * PAGE_SIZE;
 
 	task_protections((unsigned long) &init_thread_info);
+	os_flush_stdout();
 
 	return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
 }
 
+extern int uml_exitcode;
+
 static int panic_exit(struct notifier_block *self, unsigned long unused1,
 		      void *unused2)
 {
 #ifdef CONFIG_MAGIC_SYSRQ
-	handle_sysrq('p', &current->thread.regs, NULL, NULL);
+	handle_sysrq('p', &current->thread.regs, NULL);
 #endif
+	uml_exitcode = 1;
 	machine_halt();
 	return(0);
 }
@@ -403,6 +422,11 @@
 	arch_check_bugs();
 	check_ptrace();
 	check_sigio();
+	check_devanon();
+}
+
+void apply_alternatives(void *start, void *end)
+{
 }
 
 /*
diff -Nru a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
--- a/arch/um/kernel/umid.c	2003-05-25 17:00:00 -07:00
+++ b/arch/um/kernel/umid.c	2004-08-24 02:08:18 -07:00
@@ -5,7 +5,6 @@
 
 #include <stdio.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
@@ -33,18 +32,19 @@
 static int umid_is_random = 1;
 static int umid_inited = 0;
 
-static int make_umid(void);
+static int make_umid(int (*printer)(const char *fmt, ...));
 
-static int __init set_umid(char *name, int is_random)
+static int __init set_umid(char *name, int is_random,
+			   int (*printer)(const char *fmt, ...))
 {
 	if(umid_inited){
-		printk("Unique machine name can't be set twice\n");
+		(*printer)("Unique machine name can't be set twice\n");
 		return(-1);
 	}
 
 	if(strlen(name) > UMID_LEN - 1)
-		printk("Unique machine name is being truncated to %s "
-		       "characters\n", UMID_LEN);
+		(*printer)("Unique machine name is being truncated to %s "
+			   "characters\n", UMID_LEN);
 	strlcpy(umid, name, sizeof(umid));
 
 	umid_is_random = is_random;
@@ -54,7 +54,7 @@
 
 static int __init set_umid_arg(char *name, int *add)
 {
-	return(set_umid(name, 0));
+	return(set_umid(name, 0, printf));
 }
 
 __uml_setup("umid=", set_umid_arg,
@@ -67,7 +67,7 @@
 {
 	int n;
 
-	if(!umid_inited && make_umid()) return(-1);
+	if(!umid_inited && make_umid(printk)) return(-1);
 
 	n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
 	if(n > len){
@@ -85,22 +85,23 @@
 {
 	char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
 	char pid[sizeof("nnnnn\0")];
-	int fd;
+	int fd, n;
 
 	if(umid_file_name("pid", file, sizeof(file))) return 0;
 
 	fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 
 			  0644);
 	if(fd < 0){
-		printk("Open of machine pid file \"%s\" failed - "
-		       "errno = %d\n", file, -fd);
+		printf("Open of machine pid file \"%s\" failed - "
+		       "err = %d\n", file, -fd);
 		return 0;
 	}
 
 	sprintf(pid, "%d\n", os_getpid());
-	if(write(fd, pid, strlen(pid)) != strlen(pid))
-		printk("Write of pid file failed - errno = %d\n", errno);
-	close(fd);
+	n = os_write_file(fd, pid, strlen(pid));
+	if(n != strlen(pid))
+		printf("Write of pid file failed - err = %d\n", -n);
+	os_close_file(fd);
 	return 0;
 }
 
@@ -111,7 +112,8 @@
 	int len;
 	char file[256];
 
-	if((directory = opendir(dir)) == NULL){
+	directory = opendir(dir);
+	if(directory == NULL){
 		printk("actually_do_remove : couldn't open directory '%s', "
 		       "errno = %d\n", dir, errno);
 		return(1);
@@ -160,22 +162,24 @@
 {
 	char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
 	char pid[sizeof("nnnnn\0")], *end;
-	int dead, fd, p;
+	int dead, fd, p, n;
 
 	sprintf(file, "%s/pid", dir);
 	dead = 0;
-	if((fd = os_open_file(file, of_read(OPENFLAGS()), 0)) < 0){
+	fd = os_open_file(file, of_read(OPENFLAGS()), 0);
+	if(fd < 0){
 		if(fd != -ENOENT){
 			printk("not_dead_yet : couldn't open pid file '%s', "
-			       "errno = %d\n", file, -fd);
+			       "err = %d\n", file, -fd);
 			return(1);
 		}
 		dead = 1;
 	}
 	if(fd > 0){
-		if(read(fd, pid, sizeof(pid)) < 0){
+		n = os_read_file(fd, pid, sizeof(pid));
+		if(n < 0){
 			printk("not_dead_yet : couldn't read pid file '%s', "
-			       "errno = %d\n", file, errno);
+			       "err = %d\n", file, -n);
 			return(1);
 		}
 		p = strtoul(pid, &end, 0);
@@ -197,7 +201,7 @@
 	if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
 		uml_dir = malloc(strlen(name) + 1);
 		if(uml_dir == NULL){
-			printk("Failed to malloc uml_dir - error = %d\n",
+			printf("Failed to malloc uml_dir - error = %d\n",
 			       errno);
 			uml_dir = name;
 			return(0);
@@ -217,7 +221,7 @@
 		char *home = getenv("HOME");
 
 		if(home == NULL){
-			printk("make_uml_dir : no value in environment for "
+			printf("make_uml_dir : no value in environment for "
 			       "$HOME\n");
 			exit(1);
 		}
@@ -232,57 +236,59 @@
 		dir[len + 1] = '\0';
 	}
 
-	if((uml_dir = malloc(strlen(dir) + 1)) == NULL){
+	uml_dir = malloc(strlen(dir) + 1);
+	if(uml_dir == NULL){
 		printf("make_uml_dir : malloc failed, errno = %d\n", errno);
 		exit(1);
 	}
 	strcpy(uml_dir, dir);
 	
 	if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
-	        printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
+	        printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
 		return(-1);
 	}
 	return 0;
 }
 
-static int __init make_umid(void)
+static int __init make_umid(int (*printer)(const char *fmt, ...))
 {
 	int fd, err;
 	char tmp[strlen(uml_dir) + UMID_LEN + 1];
 
 	strlcpy(tmp, uml_dir, sizeof(tmp));
 
-	if(*umid == 0){
+	if(!umid_inited){
 		strcat(tmp, "XXXXXX");
 		fd = mkstemp(tmp);
 		if(fd < 0){
-			printk("make_umid - mkstemp failed, errno = %d\n",
-			       errno);
+			(*printer)("make_umid - mkstemp failed, errno = %d\n",
+				   errno);
 			return(1);
 		}
 
-		close(fd);
+		os_close_file(fd);
 		/* There's a nice tiny little race between this unlink and
 		 * the mkdir below.  It'd be nice if there were a mkstemp
 		 * for directories.
 		 */
 		unlink(tmp);
-		set_umid(&tmp[strlen(uml_dir)], 1);
+		set_umid(&tmp[strlen(uml_dir)], 1, printer);
 	}
 	
 	sprintf(tmp, "%s%s", uml_dir, umid);
 
-	if((err = mkdir(tmp, 0777)) < 0){
+	err = mkdir(tmp, 0777);
+	if(err < 0){
 		if(errno == EEXIST){
 			if(not_dead_yet(tmp)){
-				printk("umid '%s' is in use\n", umid);
+				(*printer)("umid '%s' is in use\n", umid);
 				return(-1);
 			}
 			err = mkdir(tmp, 0777);
 		}
 	}
 	if(err < 0){
-		printk("Failed to create %s - errno = %d\n", umid, errno);
+		(*printer)("Failed to create %s - errno = %d\n", umid, errno);
 		return(-1);
 	}
 
@@ -295,7 +301,13 @@
 );
 
 __uml_postsetup(make_uml_dir);
-__uml_postsetup(make_umid);
+
+static int __init make_umid_setup(void)
+{
+	return(make_umid(printf));
+}
+
+__uml_postsetup(make_umid_setup);
 __uml_postsetup(create_pid_file);
 
 /*
diff -Nru a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/kernel/uml.lds.S	2004-08-24 02:08:30 -07:00
@@ -0,0 +1,96 @@
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_FORMAT(ELF_FORMAT)
+OUTPUT_ARCH(ELF_ARCH)
+ENTRY(_start)
+jiffies = jiffies_64;
+
+SECTIONS
+{
+  . = START + SIZEOF_HEADERS;
+
+  __binary_start = .;
+#ifdef MODE_TT
+  .thread_private : {
+    __start_thread_private = .;
+    errno = .;
+    . += 4;
+    arch/um/kernel/tt/unmap_fin.o (.data)
+    __end_thread_private = .;
+  }
+  . = ALIGN(4096);
+  .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
+#endif
+
+  . = ALIGN(4096);		/* Init code and data */
+  _stext = .;
+  __init_begin = .;
+  .init.text : {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
+  . = ALIGN(4096);
+  .text      :
+  {
+    *(.text)
+    SCHED_TEXT
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+    *(.gnu.linkonce.t*)
+  }
+
+  #include "asm/common.lds.S"
+
+  init.data : { *(init.data) }
+  .data    :
+  {
+    . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
+    *(.data.init_task)
+    *(.data)
+    *(.gnu.linkonce.d*)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  .ctors         :
+  {
+    *(.ctors)
+  }
+  .dtors         :
+  {
+    *(.dtors)
+  }
+
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  . = ALIGN(0x1000);
+  .sbss      :
+  {
+   __bss_start = .;
+   PROVIDE(_bss_start = .);
+   *(.sbss)
+   *(.scommon)
+  }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -Nru a/arch/um/kernel/user_syms.c b/arch/um/kernel/user_syms.c
--- a/arch/um/kernel/user_syms.c	2003-01-18 17:23:05 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,113 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <utime.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/vfs.h>
-#include <sys/ioctl.h>
-#include "user_util.h"
-#include "mem_user.h"
-#include "uml-config.h"
-
-/* Had to steal this from linux/module.h because that file can't be included
- * since this includes various user-level headers.
- */
-
-struct module_symbol
-{
-	unsigned long value;
-	const char *name;
-};
-
-/* Indirect stringification.  */
-
-#define __MODULE_STRING_1(x)	#x
-#define __MODULE_STRING(x)	__MODULE_STRING_1(x)
-
-#if !defined(__AUTOCONF_INCLUDED__)
-
-#define __EXPORT_SYMBOL(sym,str)   error config_must_be_included_before_module
-#define EXPORT_SYMBOL(var)	   error config_must_be_included_before_module
-#define EXPORT_SYMBOL_NOVERS(var)  error config_must_be_included_before_module
-
-#elif !defined(UML_CONFIG_MODULES)
-
-#define __EXPORT_SYMBOL(sym,str)
-#define EXPORT_SYMBOL(var)
-#define EXPORT_SYMBOL_NOVERS(var)
-
-#else
-
-#define __EXPORT_SYMBOL(sym, str)			\
-const char __kstrtab_##sym[]				\
-__attribute__((section(".kstrtab"))) = str;		\
-const struct module_symbol __ksymtab_##sym 		\
-__attribute__((section("__ksymtab"))) =			\
-{ (unsigned long)&sym, __kstrtab_##sym }
-
-#if defined(__MODVERSIONS__) || !defined(UML_CONFIG_MODVERSIONS)
-#define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
-#else
-#define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
-#endif
-
-#define EXPORT_SYMBOL_NOVERS(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
-
-#endif
-
-EXPORT_SYMBOL(__errno_location);
-
-EXPORT_SYMBOL(access);
-EXPORT_SYMBOL(open);
-EXPORT_SYMBOL(open64);
-EXPORT_SYMBOL(close);
-EXPORT_SYMBOL(read);
-EXPORT_SYMBOL(write);
-EXPORT_SYMBOL(dup2);
-EXPORT_SYMBOL(__xstat);
-EXPORT_SYMBOL(__lxstat);
-EXPORT_SYMBOL(__lxstat64);
-EXPORT_SYMBOL(lseek);
-EXPORT_SYMBOL(lseek64);
-EXPORT_SYMBOL(chown);
-EXPORT_SYMBOL(truncate);
-EXPORT_SYMBOL(utime);
-EXPORT_SYMBOL(chmod);
-EXPORT_SYMBOL(rename);
-EXPORT_SYMBOL(__xmknod);
-
-EXPORT_SYMBOL(symlink);
-EXPORT_SYMBOL(link);
-EXPORT_SYMBOL(unlink);
-EXPORT_SYMBOL(readlink);
-
-EXPORT_SYMBOL(mkdir);
-EXPORT_SYMBOL(rmdir);
-EXPORT_SYMBOL(opendir);
-EXPORT_SYMBOL(readdir);
-EXPORT_SYMBOL(closedir);
-EXPORT_SYMBOL(seekdir);
-EXPORT_SYMBOL(telldir);
-
-EXPORT_SYMBOL(ioctl);
-
-extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes,
-			__off64_t __offset);
-extern ssize_t pwrite64 (int __fd, __const void *__buf, size_t __n,
-			 __off64_t __offset);
-EXPORT_SYMBOL(pread64);
-EXPORT_SYMBOL(pwrite64);
-
-EXPORT_SYMBOL(statfs);
-EXPORT_SYMBOL(statfs64);
-
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(getuid);
-
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strstr);
-
-EXPORT_SYMBOL(find_iomem);
diff -Nru a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
--- a/arch/um/kernel/user_util.c	2004-06-24 01:55:46 -07:00
+++ b/arch/um/kernel/user_util.c	2004-08-24 02:08:27 -07:00
@@ -5,7 +5,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
 #include <sys/mman.h> 
@@ -81,10 +80,10 @@
 	int status, ret;
 
 	while(1){
-		if(((ret = waitpid(pid, &status, WUNTRACED)) < 0) ||
+		CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
+		if((ret < 0) ||
 		   !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
 			if(ret < 0){
-				if(errno == EINTR) continue;
 				printk("wait failed, errno = %d\n",
 				       errno);
 			}
@@ -118,29 +117,36 @@
 	}
 }
 
-int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags)
-{
-	int pid;
-
-	pid = clone(fn, sp, flags, arg);
- 	if(pid < 0) return(-1);
-	wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
-	ptrace(PTRACE_CONT, pid, 0, 0);
-	return(pid);
-}
-
-int raw(int fd, int complain)
+int __raw(int fd, int complain, int now)
 {
 	struct termios tt;
 	int err;
+	int when;
+
+	CATCH_EINTR(err = tcgetattr(fd, &tt));
+
+	if (err < 0) {
+		if (complain)
+			printk("tcgetattr failed, errno = %d\n", errno);
+		return(-errno);
+	}
 
-	tcgetattr(fd, &tt);
 	cfmakeraw(&tt);
-	err = tcsetattr(fd, TCSANOW, &tt);
-	if((err < 0) && complain){
-		printk("tcsetattr failed, errno = %d\n", errno);
+
+	if (now)
+		when = TCSANOW;
+	else
+		when = TCSADRAIN;
+
+	CATCH_EINTR(err = tcsetattr(fd, when, &tt));
+
+	if (err < 0) {
+		if (complain)
+			printk("tcsetattr failed, errno = %d\n", errno);
 		return(-errno);
 	}
+	/*XXX: tcsetattr could have applied only some changes
+	 * (and cfmakeraw() is a set of changes) */
 	return(0);
 }
 
diff -Nru a/arch/um/main.c b/arch/um/main.c
--- a/arch/um/main.c	2003-01-18 15:41:33 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,195 +0,0 @@
-/* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <unistd.h>
-#include <stdio.h> 
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/resource.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-#include <asm/page.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "mem_user.h"
-#include "signal_user.h"
-#include "user.h"
-#include "init.h"
-#include "mode.h"
-#include "choose-mode.h"
-#include "uml-config.h"
-
-/* Set in set_stklim, which is called from main and __wrap_malloc.  
- * __wrap_malloc only calls it if main hasn't started.
- */
-unsigned long stacksizelim;
-
-/* Set in main */
-char *linux_prog;
-
-#define PGD_BOUND (4 * 1024 * 1024)
-#define STACKSIZE (8 * 1024 * 1024)
-#define THREAD_NAME_LEN (256)
-
-static void set_stklim(void)
-{
-	struct rlimit lim;
-
-	if(getrlimit(RLIMIT_STACK, &lim) < 0){
-		perror("getrlimit");
-		exit(1);
-	}
-	if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){
-		lim.rlim_cur = STACKSIZE;
-		if(setrlimit(RLIMIT_STACK, &lim) < 0){
-			perror("setrlimit");
-			exit(1);
-		}
-	}
-	stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
-}
-
-static __init void do_uml_initcalls(void)
-{
-	initcall_t *call;
-
-	call = &__uml_initcall_start;
-	while (call < &__uml_initcall_end){;
-		(*call)();
-		call++;
-	}
-}
-
-static void last_ditch_exit(int sig)
-{
-	CHOOSE_MODE(kmalloc_ok = 0, (void) 0);
-	signal(SIGINT, SIG_DFL);
-	signal(SIGTERM, SIG_DFL);
-	signal(SIGHUP, SIG_DFL);
-	uml_cleanup();
-	exit(1);
-}
-
-extern int uml_exitcode;
-
-int main(int argc, char **argv, char **envp)
-{
-	char **new_argv;
-	sigset_t mask;
-	int ret, i;
-
-	/* Enable all signals except SIGIO - in some environments, we can 
-	 * enter with some signals blocked
-	 */
-
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGIO);
-	if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
-		perror("sigprocmask");
-		exit(1);
-	}
-
-#ifdef UML_CONFIG_MODE_TT
-	/* Allocate memory for thread command lines */
-	if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
-
-		char padding[THREAD_NAME_LEN] = { 
-			[ 0 ...  THREAD_NAME_LEN - 2] = ' ', '\0' 
-		};
-
-		new_argv = malloc((argc + 2) * sizeof(char*));
-		if(!new_argv) {
-			perror("Allocating extended argv");
-			exit(1);
-		}	
-		
-		new_argv[0] = argv[0];
-		new_argv[1] = padding;
-		
-		for(i = 2; i <= argc; i++)
-			new_argv[i] = argv[i - 1];
-		new_argv[argc + 1] = NULL;
-		
-		execvp(new_argv[0], new_argv);
-		perror("execing with extended args");
-		exit(1);
-	}	
-#endif
-
-	linux_prog = argv[0];
-
-	set_stklim();
-
-	if((new_argv = malloc((argc + 1) * sizeof(char *))) == NULL){
-		perror("Mallocing argv");
-		exit(1);
-	}
-	for(i=0;i<argc;i++){
-		if((new_argv[i] = strdup(argv[i])) == NULL){
-			perror("Mallocing an arg");
-			exit(1);
-		}
-	}
-	new_argv[argc] = NULL;
-
-	set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-	set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-	set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-
-	do_uml_initcalls();
-	ret = linux_main(argc, argv);
-	
-	/* Reboot */
-	if(ret){
-		printf("\n");
-		execvp(new_argv[0], new_argv);
-		perror("Failed to exec kernel");
-		ret = 1;
-	}
-	printf("\n");
-	return(uml_exitcode);
-}
-
-#define CAN_KMALLOC() \
-	(kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1))
-
-extern void *__real_malloc(int);
-
-void *__wrap_malloc(int size)
-{
-	if(CAN_KMALLOC())
-		return(um_kmalloc(size));
-	else
-		return(__real_malloc(size));
-}
-
-void *__wrap_calloc(int n, int size)
-{
-	void *ptr = __wrap_malloc(n * size);
-
-	if(ptr == NULL) return(NULL);
-	memset(ptr, 0, n * size);
-	return(ptr);
-}
-
-extern void __real_free(void *);
-
-void __wrap_free(void *ptr)
-{
-	if(CAN_KMALLOC()) kfree(ptr);
-	else __real_free(ptr);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
--- a/arch/um/os-Linux/Makefile	2002-12-16 23:54:52 -08:00
+++ b/arch/um/os-Linux/Makefile	2004-08-24 02:08:18 -07:00
@@ -3,13 +3,9 @@
 # Licensed under the GPL
 #
 
-obj-y = file.o process.o tty.o drivers/
+obj-y = file.o process.o tty.o user_syms.o drivers/
 
 USER_OBJS := $(foreach file,file.o process.o tty.o,$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-
-archmrproper:
diff -Nru a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
--- a/arch/um/os-Linux/drivers/ethertap_kern.c	2003-06-03 00:00:18 -07:00
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c	2004-08-24 02:08:18 -07:00
@@ -8,7 +8,6 @@
 #include "linux/init.h"
 #include "linux/netdevice.h"
 #include "linux/etherdevice.h"
-#include "linux/init.h"
 #include "net_kern.h"
 #include "net_user.h"
 #include "etap.h"
diff -Nru a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
--- a/arch/um/os-Linux/drivers/ethertap_user.c	2002-12-28 18:27:38 -08:00
+++ b/arch/um/os-Linux/drivers/ethertap_user.c	2004-08-24 02:08:27 -07:00
@@ -8,7 +8,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <stddef.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <sys/errno.h>
 #include <sys/socket.h>
@@ -17,6 +16,7 @@
 #include <net/if.h>
 #include "user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "net_user.h"
 #include "etap.h"
 #include "helper.h"
@@ -42,13 +42,14 @@
 {
 	struct addr_change change;
 	void *output;
+	int n;
 
 	change.what = op;
 	memcpy(change.addr, addr, sizeof(change.addr));
 	memcpy(change.netmask, netmask, sizeof(change.netmask));
-	if(write(fd, &change, sizeof(change)) != sizeof(change))
-		printk("etap_change - request failed, errno = %d\n",
-		       errno);
+	n = os_write_file(fd, &change, sizeof(change));
+	if(n != sizeof(change))
+		printk("etap_change - request failed, err = %d\n", -n);
 	output = um_kmalloc(page_size());
 	if(output == NULL)
 		printk("etap_change : Failed to allocate output buffer\n");
@@ -82,15 +83,15 @@
 	struct etap_pre_exec_data *data = arg;
 
 	dup2(data->control_remote, 1);
-	close(data->data_me);
-	close(data->control_me);
+	os_close_file(data->data_me);
+	os_close_file(data->control_me);
 }
 
 static int etap_tramp(char *dev, char *gate, int control_me, 
 		      int control_remote, int data_me, int data_remote)
 {
 	struct etap_pre_exec_data pe_data;
-	int pid, status, err;
+	int pid, status, err, n;
 	char version_buf[sizeof("nnnnn\0")];
 	char data_fd_buf[sizeof("nnnnnn\0")];
 	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
@@ -114,21 +115,22 @@
 	pe_data.data_me = data_me;
 	pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
 
-	if(pid < 0) err = errno;
-	close(data_remote);
-	close(control_remote);
-	if(read(control_me, &c, sizeof(c)) != sizeof(c)){
-		printk("etap_tramp : read of status failed, errno = %d\n",
-		       errno);
-		return(EINVAL);
+	if(pid < 0) err = pid;
+	os_close_file(data_remote);
+	os_close_file(control_remote);
+	n = os_read_file(control_me, &c, sizeof(c));
+	if(n != sizeof(c)){
+		printk("etap_tramp : read of status failed, err = %d\n", -n);
+		return(-EINVAL);
 	}
 	if(c != 1){
 		printk("etap_tramp : uml_net failed\n");
-		err = EINVAL;
-		if(waitpid(pid, &status, 0) < 0) err = errno;
-		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)){
+		err = -EINVAL;
+		CATCH_EINTR(n = waitpid(pid, &status, 0));
+		if(n < 0)
+			err = -errno;
+		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
 			printk("uml_net didn't exit with status 1\n");
-		}
 	}
 	return(err);
 }
@@ -143,14 +145,14 @@
 	if(err) return(err);
 
 	err = os_pipe(data_fds, 0, 0);
-	if(err){
-		printk("data os_pipe failed - errno = %d\n", -err);
+	if(err < 0){
+		printk("data os_pipe failed - err = %d\n", -err);
 		return(err);
 	}
 
 	err = os_pipe(control_fds, 1, 0);
-	if(err){
-		printk("control os_pipe failed - errno = %d\n", -err);
+	if(err < 0){
+		printk("control os_pipe failed - err = %d\n", -err);
 		return(err);
 	}
 	
@@ -167,9 +169,9 @@
 		kfree(output);
 	}
 
-	if(err != 0){
-		printk("etap_tramp failed - errno = %d\n", err);
-		return(-err);
+	if(err < 0){
+		printk("etap_tramp failed - err = %d\n", -err);
+		return(err);
 	}
 
 	pri->data_fd = data_fds[0];
@@ -183,11 +185,11 @@
 	struct ethertap_data *pri = data;
 
 	iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
-	close(fd);
+	os_close_file(fd);
 	os_shutdown_socket(pri->data_fd, 1, 1);
-	close(pri->data_fd);
+	os_close_file(pri->data_fd);
 	pri->data_fd = -1;
-	close(pri->control_fd);
+	os_close_file(pri->control_fd);
 	pri->control_fd = -1;
 }
 
diff -Nru a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
--- a/arch/um/os-Linux/drivers/tuntap_user.c	2003-05-25 17:00:00 -07:00
+++ b/arch/um/os-Linux/drivers/tuntap_user.c	2004-08-24 02:08:27 -07:00
@@ -8,7 +8,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -19,6 +18,7 @@
 #include "net_user.h"
 #include "tuntap.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "user.h"
 #include "helper.h"
 #include "os.h"
@@ -61,7 +61,7 @@
 	struct tuntap_pre_exec_data *data = arg;
 	
 	dup2(data->stdout, 1);
-	close(data->close_me);
+	os_close_file(data->close_me);
 }
 
 static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
@@ -86,7 +86,7 @@
 
 	if(pid < 0) return(-pid);
 
-	close(remote);
+	os_close_file(remote);
 
 	msg.msg_name = NULL;
 	msg.msg_namelen = 0;
@@ -107,19 +107,19 @@
 	if(n < 0){
 		printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", 
 		       errno);
-		return(errno);
+		return(-errno);
 	}
-	waitpid(pid, NULL, 0);
+	CATCH_EINTR(waitpid(pid, NULL, 0));
 
 	cmsg = CMSG_FIRSTHDR(&msg);
 	if(cmsg == NULL){
 		printk("tuntap_open_tramp : didn't receive a message\n");
-		return(EINVAL);
+		return(-EINVAL);
 	}
 	if((cmsg->cmsg_level != SOL_SOCKET) || 
 	   (cmsg->cmsg_type != SCM_RIGHTS)){
 		printk("tuntap_open_tramp : didn't receive a descriptor\n");
-		return(EINVAL);
+		return(-EINVAL);
 	}
 	*fd_out = ((int *) CMSG_DATA(cmsg))[0];
 	return(0);
@@ -133,27 +133,29 @@
 	int err, fds[2], len, used;
 
 	err = tap_open_common(pri->dev, pri->gate_addr);
-	if(err) return(err);
+	if(err < 0)
+		return(err);
 
 	if(pri->fixed_config){
-		if((pri->fd = open("/dev/net/tun", O_RDWR)) < 0){
-			printk("Failed to open /dev/net/tun, errno = %d\n",
-			       errno);
-			return(-errno);
+		pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0);
+		if(pri->fd < 0){
+			printk("Failed to open /dev/net/tun, err = %d\n",
+			       -pri->fd);
+			return(pri->fd);
 		}
 		memset(&ifr, 0, sizeof(ifr));
-		ifr.ifr_flags = IFF_TAP;
+		ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 		strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
 		if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
-			printk("TUNSETIFF failed, errno = %d", errno);
-			close(pri->fd);
+			printk("TUNSETIFF failed, errno = %d\n", errno);
+			os_close_file(pri->fd);
 			return(-errno);
 		}
 	}
 	else {
 		err = os_pipe(fds, 0, 0);
-		if(err){
-			printk("tuntap_open : os_pipe failed - errno = %d\n",
+		if(err < 0){
+			printk("tuntap_open : os_pipe failed - err = %d\n",
 			       -err);
 			return(err);
 		}
@@ -166,19 +168,19 @@
 					fds[1], buffer, len, &used);
 
 		output = buffer;
-		if(err == 0){
-			pri->dev_name = uml_strdup(buffer);
-			output += IFNAMSIZ;
-			printk(output);
-			free_output_buffer(buffer);
-		}
-		else {
-			printk(output);
+		if(err < 0) {
+			printk("%s", output);
 			free_output_buffer(buffer);
-			printk("tuntap_open_tramp failed - errno = %d\n", err);
-			return(-err);
+			printk("tuntap_open_tramp failed - err = %d\n", -err);
+			return(err);
 		}
-		close(fds[0]);
+
+		pri->dev_name = uml_strdup(buffer);
+		output += IFNAMSIZ;
+		printk("%s", output);
+		free_output_buffer(buffer);
+
+		os_close_file(fds[0]);
 		iter_addresses(pri->dev, open_addr, pri->dev_name);
 	}
 
@@ -191,7 +193,7 @@
 
 	if(!pri->fixed_config) 
 		iter_addresses(pri->dev, close_addr, pri->dev_name);
-	close(fd);
+	os_close_file(fd);
 	pri->fd = -1;
 }
 
diff -Nru a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
--- a/arch/um/os-Linux/file.c	2003-01-18 12:26:19 -08:00
+++ b/arch/um/os-Linux/file.c	2004-08-24 02:08:18 -07:00
@@ -8,6 +8,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/ioctl.h>
@@ -17,33 +19,235 @@
 #include "user.h"
 #include "kern_util.h"
 
-int os_file_type(char *file)
+static void copy_stat(struct uml_stat *dst, struct stat64 *src)
+{
+	*dst = ((struct uml_stat) {
+		.ust_dev     = src->st_dev,     /* device */
+		.ust_ino     = src->st_ino,     /* inode */
+		.ust_mode    = src->st_mode,    /* protection */
+		.ust_nlink   = src->st_nlink,   /* number of hard links */
+		.ust_uid     = src->st_uid,     /* user ID of owner */
+		.ust_gid     = src->st_gid,     /* group ID of owner */
+		.ust_size    = src->st_size,    /* total size, in bytes */
+		.ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
+		.ust_blocks  = src->st_blocks,  /* number of blocks allocated */
+		.ust_atime   = src->st_atime,   /* time of last access */
+		.ust_mtime   = src->st_mtime,   /* time of last modification */
+		.ust_ctime   = src->st_ctime,   /* time of last change */
+	});
+}
+
+int os_stat_fd(const int fd, struct uml_stat *ubuf)
+{
+	struct stat64 sbuf;
+	int err;
+
+	do {
+		err = fstat64(fd, &sbuf);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	if(ubuf != NULL)
+		copy_stat(ubuf, &sbuf);
+	return(err);
+}
+
+int os_stat_file(const char *file_name, struct uml_stat *ubuf)
+{
+	struct stat64 sbuf;
+	int err;
+
+	do {
+		err = stat64(file_name, &sbuf);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	if(ubuf != NULL)
+		copy_stat(ubuf, &sbuf);
+	return(err);
+}
+
+int os_access(const char* file, int mode)
+{
+	int amode, err;
+
+	amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
+	      (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
+
+	err = access(file, amode);
+	if(err < 0)
+		return(-errno);
+
+	return(0);
+}
+
+void os_print_error(int error, const char* str)
+{
+	errno = error < 0 ? -error : error;
+
+	perror(str);
+}
+
+/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
+int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
+{
+	int err;
+
+	err = ioctl(fd, cmd, arg);
+	if(err < 0)
+		return(-errno);
+
+	return(err);
+}
+
+int os_window_size(int fd, int *rows, int *cols)
+{
+	struct winsize size;
+
+	if(ioctl(fd, TIOCGWINSZ, &size) < 0)
+		return(-errno);
+
+	*rows = size.ws_row;
+	*cols = size.ws_col;
+
+	return(0);
+}
+
+int os_new_tty_pgrp(int fd, int pid)
 {
-	struct stat64 buf;
+	if(ioctl(fd, TIOCSCTTY, 0) < 0){
+		printk("TIOCSCTTY failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	if(tcsetpgrp(fd, pid) < 0){
+		printk("tcsetpgrp failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	return(0);
+}
+
+/* FIXME: ensure namebuf in os_get_if_name is big enough */
+int os_get_ifname(int fd, char* namebuf)
+{
+	if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
+		return(-errno);
+
+	return(0);
+}
+
+int os_set_slip(int fd)
+{
+	int disc, sencap;
+
+	disc = N_SLIP;
+	if(ioctl(fd, TIOCSETD, &disc) < 0){
+		printk("Failed to set slip line discipline - "
+		       "errno = %d\n", errno);
+		return(-errno);
+	}
+
+	sencap = 0;
+	if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
+		printk("Failed to set slip encapsulation - "
+		       "errno = %d\n", errno);
+		return(-errno);
+	}
+
+	return(0);
+}
+
+int os_set_owner(int fd, int pid)
+{
+	if(fcntl(fd, F_SETOWN, pid) < 0){
+		int save_errno = errno;
+
+		if(fcntl(fd, F_GETOWN, 0) != pid)
+			return(-save_errno);
+	}
+
+	return(0);
+}
+
+/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
+int os_sigio_async(int master, int slave)
+{
+	int flags;
 
-	if(stat64(file, &buf) == -1)
+	flags = fcntl(master, F_GETFL);
+	if(flags < 0) {
+		printk("fcntl F_GETFL failed, errno = %d\n", errno);
 		return(-errno);
+	}
+
+	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+	   (fcntl(master, F_SETOWN, os_getpid()) < 0)){
+		printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
+		printk("fcntl F_SETFL failed, errno = %d\n", errno);
+		return(-errno);
+	}
 
-	if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
-	else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
-	else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
-	else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
-	else if(S_ISFIFO(buf.st_mode)) return(OS_TYPE_FIFO);
-	else if(S_ISSOCK(buf.st_mode)) return(OS_TYPE_SOCK);
+	return(0);
+}
+
+int os_mode_fd(int fd, int mode)
+{
+	int err;
+
+	do {
+		err = fchmod(fd, mode);
+	} while((err < 0) && (errno==EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	return(0);
+}
+
+int os_file_type(char *file)
+{
+	struct uml_stat buf;
+	int err;
+
+	err = os_stat_file(file, &buf);
+	if(err < 0)
+		return(err);
+
+	if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
+	else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
+	else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
+	else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
+	else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
+	else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
 	else return(OS_TYPE_FILE);
 }
 
 int os_file_mode(char *file, struct openflags *mode_out)
 {
+	int err;
+
 	*mode_out = OPENFLAGS();
 
-	if(!access(file, W_OK)) *mode_out = of_write(*mode_out);
-	else if(errno != EACCES) 
-		return(-errno);
+	err = os_access(file, OS_ACC_W_OK);
+	if((err < 0) && (err != -EACCES))
+		return(err);
 
-	if(!access(file, R_OK)) *mode_out = of_read(*mode_out);
-	else if(errno != EACCES) 
-		return(-errno);
+	*mode_out = of_write(*mode_out);
+
+	err = os_access(file, OS_ACC_R_OK);
+	if((err < 0) && (err != -EACCES))
+		return(err);
+
+	*mode_out = of_read(*mode_out);
 
 	return(0);
 }
@@ -63,16 +267,14 @@
 	if(flags.e) f |= O_EXCL;
 
 	fd = open64(file, f, mode);
-	if(fd < 0) return(-errno);
-	
-	if(flags.cl){
-		if(fcntl(fd, F_SETFD, 1)){
-			close(fd);
-			return(-errno);
-		}
+	if(fd < 0)
+		return(-errno);
+
+	if(flags.cl && fcntl(fd, F_SETFD, 1)){
+		os_close_file(fd);
+		return(-errno);
 	}
 
- 	return(fd);
 	return(fd);
 }
 
@@ -90,7 +292,7 @@
 
 	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
 	if(err)
-		return(err);
+		return(-errno);
 
 	return(fd);
 }
@@ -109,88 +311,162 @@
 	return(0);
 }
 
-int os_read_file(int fd, void *buf, int len)
+static int fault_buffer(void *start, int len,
+			int (*copy_proc)(void *addr, void *buf, int len))
 {
-	int n;
+	int page = getpagesize(), i;
+	char c;
 
-	/* Force buf into memory if it's not already. */
+	for(i = 0; i < len; i += page){
+		if((*copy_proc)(start + i, &c, sizeof(c)))
+			return(-EFAULT);
+	}
+	if((len % page) != 0){
+		if((*copy_proc)(start + len - 1, &c, sizeof(c)))
+			return(-EFAULT);
+	}
+	return(0);
+}
 
-	/* XXX This fails if buf is kernel memory */
-#ifdef notdef
-	if(copy_to_user_proc(buf, &c, sizeof(c)))
-		return(-EFAULT);
-#endif
+static int file_io(int fd, void *buf, int len,
+		   int (*io_proc)(int fd, void *buf, int len),
+		   int (*copy_user_proc)(void *addr, void *buf, int len))
+{
+	int n, err;
+
+	do {
+		n = (*io_proc)(fd, buf, len);
+		if((n < 0) && (errno == EFAULT)){
+			err = fault_buffer(buf, len, copy_user_proc);
+			if(err)
+				return(err);
+			n = (*io_proc)(fd, buf, len);
+		}
+	} while((n < 0) && (errno == EINTR));
 
-	n = read(fd, buf, len);
 	if(n < 0)
 		return(-errno);
 	return(n);
 }
 
-int os_write_file(int fd, void *buf, int count)
+int os_read_file(int fd, void *buf, int len)
 {
-	int n;
-
-	/* Force buf into memory if it's not already. */
-	
-	/* XXX This fails if buf is kernel memory */
-#ifdef notdef
-	if(copy_to_user_proc(buf, buf, buf[0]))
-		return(-EFAULT);
-#endif
+	return(file_io(fd, buf, len, (int (*)(int, void *, int)) read,
+		       copy_from_user_proc));
+}
 
-	n = write(fd, buf, count);
-	if(n < 0)
-		return(-errno);
-	return(n);
+int os_write_file(int fd, const void *buf, int len)
+{
+	return(file_io(fd, (void *) buf, len,
+		       (int (*)(int, void *, int)) write, copy_to_user_proc));
 }
 
 int os_file_size(char *file, long long *size_out)
 {
-	struct stat64 buf;
+	struct uml_stat buf;
+	int err;
 
-	if(stat64(file, &buf) == -1){
-		printk("Couldn't stat \"%s\" : errno = %d\n", file, errno);
-		return(-errno);
+	err = os_stat_file(file, &buf);
+	if(err < 0){
+		printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+		return(err);
 	}
-	if(S_ISBLK(buf.st_mode)){
+
+	if(S_ISBLK(buf.ust_mode)){
 		int fd, blocks;
 
-		if((fd = open64(file, O_RDONLY)) < 0){
-			printk("Couldn't open \"%s\", errno = %d\n", file,
-			       errno);
-			return(-errno);
+		fd = os_open_file(file, of_read(OPENFLAGS()), 0);
+		if(fd < 0){
+			printk("Couldn't open \"%s\", errno = %d\n", file, -fd);
+			return(fd);
 		}
 		if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
 			printk("Couldn't get the block size of \"%s\", "
 			       "errno = %d\n", file, errno);
-			close(fd);
-			return(-errno);
+			err = -errno;
+			os_close_file(fd);
+			return(err);
 		}
 		*size_out = ((long long) blocks) * 512;
-		close(fd);
+		os_close_file(fd);
 		return(0);
 	}
-	*size_out = buf.st_size;
+	*size_out = buf.ust_size;
+	return(0);
+}
+
+int os_file_modtime(char *file, unsigned long *modtime)
+{
+	struct uml_stat buf;
+	int err;
+
+	err = os_stat_file(file, &buf);
+	if(err < 0){
+		printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+		return(err);
+	}
+
+	*modtime = buf.ust_mtime;
 	return(0);
 }
 
+int os_get_exec_close(int fd, int* close_on_exec)
+{
+	int ret;
+
+	do {
+		ret = fcntl(fd, F_GETFD);
+	} while((ret < 0) && (errno == EINTR)) ;
+
+	if(ret < 0)
+		return(-errno);
+
+	*close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
+	return(ret);
+}
+
+int os_set_exec_close(int fd, int close_on_exec)
+{
+	int flag, err;
+
+	if(close_on_exec) flag = FD_CLOEXEC;
+	else flag = 0;
+
+	do {
+		err = fcntl(fd, F_SETFD, flag);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+	return(err);
+}
+
 int os_pipe(int *fds, int stream, int close_on_exec)
 {
 	int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
 
 	err = socketpair(AF_UNIX, type, 0, fds);
-	if(err) 
+	if(err < 0)
 		return(-errno);
 
 	if(!close_on_exec)
 		return(0);
 
-	if((fcntl(fds[0], F_SETFD, 1) < 0) || (fcntl(fds[1], F_SETFD, 1) < 0))
-		printk("os_pipe : Setting FD_CLOEXEC failed, errno = %d", 
-		       errno);
+	err = os_set_exec_close(fds[0], 1);
+	if(err < 0)
+		goto error;
+
+	err = os_set_exec_close(fds[1], 1);
+	if(err < 0)
+		goto error;
 
 	return(0);
+
+ error:
+	printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
+	os_close_file(fds[1]);
+	os_close_file(fds[0]);
+	return(err);
 }
 
 int os_set_fd_async(int fd, int owner)
@@ -270,7 +546,7 @@
 		return(-EINVAL);
 	}
 	err = shutdown(fd, what);
-	if(err)
+	if(err < 0)
 		return(-errno);
 	return(0);
 }
@@ -315,7 +591,7 @@
 	return(new);
 }
 
-int create_unix_socket(char *file, int len)
+int os_create_unix_socket(char *file, int len, int close_on_exec)
 {
 	struct sockaddr_un addr;
 	int sock, err;
@@ -327,6 +603,13 @@
 		return(-errno);
 	}
 
+	if(close_on_exec) {
+		err = os_set_exec_close(sock, 1);
+		if(err < 0)
+			printk("create_unix_socket : close_on_exec failed, "
+		       "err = %d", -err);
+	}
+
 	addr.sun_family = AF_UNIX;
 
 	/* XXX Be more careful about overflow */
@@ -334,12 +617,43 @@
 
 	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
 	if (err < 0){
-		printk("create_listening_socket - bind failed, errno = %d\n",
-		       errno);
+		printk("create_listening_socket at '%s' - bind failed, "
+		       "errno = %d\n", file, errno);
 		return(-errno);
 	}
 
 	return(sock);
+}
+
+void os_flush_stdout(void)
+{
+	fflush(stdout);
+}
+
+int os_lock_file(int fd, int excl)
+{
+	int type = excl ? F_WRLCK : F_RDLCK;
+	struct flock lock = ((struct flock) { .l_type	= type,
+					      .l_whence	= SEEK_SET,
+					      .l_start	= 0,
+					      .l_len	= 0 } );
+	int err, save;
+
+	err = fcntl(fd, F_SETLK, &lock);
+	if(!err)
+		goto out;
+
+	save = -errno;
+	err = fcntl(fd, F_GETLK, &lock);
+	if(err){
+		err = -errno;
+		goto out;
+	}
+
+	printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
+	err = save;
+ out:
+	return(err);
 }
 
 /*
diff -Nru a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
--- a/arch/um/os-Linux/process.c	2003-01-18 12:29:27 -08:00
+++ b/arch/um/os-Linux/process.c	2004-08-24 02:08:28 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,35 +7,44 @@
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
+#include <linux/unistd.h>
 #include <sys/mman.h>
 #include <sys/wait.h>
 #include "os.h"
 #include "user.h"
+#include "user_util.h"
+
+#define ARBITRARY_ADDR -1
+#define FAILURE_PID    -1
+
+#define STAT_PATH_LEN sizeof("/proc/#######/stat\0")
+#define COMM_SCANF "%*[^)])"
 
 unsigned long os_process_pc(int pid)
 {
-	char proc_stat[sizeof("/proc/#####/stat\0")], buf[256];
+	char proc_stat[STAT_PATH_LEN], buf[256];
 	unsigned long pc;
-	int fd;
+	int fd, err;
 
 	sprintf(proc_stat, "/proc/%d/stat", pid);
 	fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("os_process_pc - couldn't open '%s', errno = %d\n", 
-		       proc_stat, errno);
-		return(-1);
+		printk("os_process_pc - couldn't open '%s', err = %d\n",
+		       proc_stat, -fd);
+		return(ARBITRARY_ADDR);
 	}
-	if(read(fd, buf, sizeof(buf)) < 0){
-		printk("os_process_pc - couldn't read '%s', errno = %d\n", 
-		       proc_stat, errno);
-		close(fd);
-		return(-1);
+	err = os_read_file(fd, buf, sizeof(buf));
+	if(err < 0){
+		printk("os_process_pc - couldn't read '%s', err = %d\n",
+		       proc_stat, -err);
+		os_close_file(fd);
+		return(ARBITRARY_ADDR);
 	}
-	close(fd);
-	pc = -1;
-	if(sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d "
+	os_close_file(fd);
+	pc = ARBITRARY_ADDR;
+	if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d %*d "
 		  "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
-		  "%*d %*d %*d %*d %ld", &pc) != 1){
+		  "%*d %*d %*d %*d %lu", &pc) != 1){
 		printk("os_process_pc - couldn't find pc in '%s'\n", buf);
 	}
 	return(pc);
@@ -43,7 +52,7 @@
 
 int os_process_parent(int pid)
 {
-	char stat[sizeof("/proc/nnnnn/stat\0")];
+	char stat[STAT_PATH_LEN];
 	char data[256];
 	int parent, n, fd;
 
@@ -52,22 +61,22 @@
 	snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
 	fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("Couldn't open '%s', errno = %d\n", stat, -fd);
-		return(-1);
+		printk("Couldn't open '%s', err = %d\n", stat, -fd);
+		return(FAILURE_PID);
 	}
 
-	n = read(fd, data, sizeof(data));
-	close(fd);
+	n = os_read_file(fd, data, sizeof(data));
+	os_close_file(fd);
 
 	if(n < 0){
-		printk("Couldn't read '%s', errno = %d\n", stat);
-		return(-1);
+		printk("Couldn't read '%s', err = %d\n", stat, -n);
+		return(FAILURE_PID);
 	}
 
-	parent = -1;
-	/* XXX This will break if there is a space in the command */
-	n = sscanf(data, "%*d %*s %*c %d", &parent);
-	if(n != 1) printk("Failed to scan '%s'\n", data);
+	parent = FAILURE_PID;
+	n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
+	if(n != 1)
+		printk("Failed to scan '%s'\n", data);
 
 	return(parent);
 }
@@ -81,13 +90,17 @@
 {
 	kill(pid, SIGKILL);
 	if(reap_child)
-		waitpid(pid, NULL, 0);
+		CATCH_EINTR(waitpid(pid, NULL, 0));
 		
 }
 
 void os_usr1_process(int pid)
 {
+#ifdef __NR_tkill
+	syscall(__NR_tkill, pid, SIGUSR1);
+#else
 	kill(pid, SIGUSR1);
+#endif
 }
 
 int os_getpid(void)
@@ -95,7 +108,7 @@
 	return(getpid());
 }
 
-int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len, 
+int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
 		  int r, int w, int x)
 {
 	void *loc;
@@ -104,8 +117,8 @@
 	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
 		(x ? PROT_EXEC : 0);
 
-	loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, 
-		   fd, off);
+	loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
+		     fd, off);
 	if(loc == MAP_FAILED)
 		return(-errno);
 	return(0);
@@ -126,7 +139,8 @@
         int err;
 
         err = munmap(addr, len);
-        if(err < 0) return(-errno);
+	if(err < 0)
+		return(-errno);
         return(0);
 }
 
diff -Nru a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
--- a/arch/um/os-Linux/tty.c	2002-11-20 20:04:11 -08:00
+++ b/arch/um/os-Linux/tty.c	2004-08-24 02:08:18 -07:00
@@ -28,10 +28,10 @@
 	struct grantpt_info info;
 	int fd;
 
-	if((fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0)) < 0){
-		printk("get_pty : Couldn't open /dev/ptmx - errno = %d\n",
-		       errno);
-		return(-1);
+	fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
+		return(fd);
 	}
 
 	info.fd = fd;
@@ -39,7 +39,7 @@
 
 	if(info.res < 0){
 		printk("get_pty : Couldn't grant pty - errno = %d\n", 
-		       info.err);
+		       -info.err);
 		return(-1);
 	}
 	if(unlockpt(fd) < 0){
diff -Nru a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/os-Linux/user_syms.c	2004-08-24 11:13:14 -07:00
@@ -0,0 +1,88 @@
+#include "linux/types.h"
+#include "linux/module.h"
+
+/* Some of this are builtin function (some are not but could in the future),
+ * so I *must* declare good prototypes for them and then EXPORT them.
+ * The kernel code uses the macro defined by include/linux/string.h,
+ * so I undef macros; the userspace code does not include that and I
+ * add an EXPORT for the glibc one.*/
+
+#undef strlen
+#undef strstr
+#undef memcpy
+#undef memset
+
+extern size_t strlen(const char *);
+extern void *memcpy(void *, const void *, size_t);
+extern void *memset(void *, int, size_t);
+extern int printf(const char *, ...);
+
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(printf);
+
+EXPORT_SYMBOL(strstr);
+
+/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
+ * However, the modules will use the CRC defined *here*, no matter if it is
+ * good; so the versions of these symbols will always match
+ */
+#define EXPORT_SYMBOL_PROTO(sym)       \
+       int sym(void);                  \
+       EXPORT_SYMBOL(sym);
+
+EXPORT_SYMBOL_PROTO(__errno_location);
+
+EXPORT_SYMBOL_PROTO(access);
+EXPORT_SYMBOL_PROTO(open);
+EXPORT_SYMBOL_PROTO(open64);
+EXPORT_SYMBOL_PROTO(close);
+EXPORT_SYMBOL_PROTO(read);
+EXPORT_SYMBOL_PROTO(write);
+EXPORT_SYMBOL_PROTO(dup2);
+EXPORT_SYMBOL_PROTO(__xstat);
+EXPORT_SYMBOL_PROTO(__lxstat);
+EXPORT_SYMBOL_PROTO(__lxstat64);
+EXPORT_SYMBOL_PROTO(lseek);
+EXPORT_SYMBOL_PROTO(lseek64);
+EXPORT_SYMBOL_PROTO(chown);
+EXPORT_SYMBOL_PROTO(truncate);
+EXPORT_SYMBOL_PROTO(utime);
+EXPORT_SYMBOL_PROTO(chmod);
+EXPORT_SYMBOL_PROTO(rename);
+EXPORT_SYMBOL_PROTO(__xmknod);
+
+EXPORT_SYMBOL_PROTO(symlink);
+EXPORT_SYMBOL_PROTO(link);
+EXPORT_SYMBOL_PROTO(unlink);
+EXPORT_SYMBOL_PROTO(readlink);
+
+EXPORT_SYMBOL_PROTO(mkdir);
+EXPORT_SYMBOL_PROTO(rmdir);
+EXPORT_SYMBOL_PROTO(opendir);
+EXPORT_SYMBOL_PROTO(readdir);
+EXPORT_SYMBOL_PROTO(closedir);
+EXPORT_SYMBOL_PROTO(seekdir);
+EXPORT_SYMBOL_PROTO(telldir);
+
+EXPORT_SYMBOL_PROTO(ioctl);
+
+EXPORT_SYMBOL_PROTO(pread64);
+EXPORT_SYMBOL_PROTO(pwrite64);
+
+EXPORT_SYMBOL_PROTO(statfs);
+EXPORT_SYMBOL_PROTO(statfs64);
+
+EXPORT_SYMBOL_PROTO(getuid);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
--- a/arch/um/sys-i386/Makefile	2003-02-05 20:16:02 -08:00
+++ b/arch/um/sys-i386/Makefile	2004-08-24 02:08:30 -07:00
@@ -1,14 +1,18 @@
-obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \
-	ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
+obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \
+	ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o time.o
 
 obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_MODULES) += module.o
 
 USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-SYMLINKS = semaphore.c highmem.c module.c
+SYMLINKS = bitops.c semaphore.c highmem.c module.c
 SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
 
+clean-files := $(SYMLINKS)
+
+bitops.c-dir = lib
 semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
@@ -24,19 +28,4 @@
 $(SYMLINKS): 
 	$(call make_link,$@)
 
-clean:
-	$(MAKE) -C util clean
-
-fastdep:
-
-dep:
-
-archmrproper:
-	rm -f $(SYMLINKS)
-
-archclean:
-
-archdep:
-
-modules:
-
+subdir- := util
diff -Nru a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
--- a/arch/um/sys-i386/bugs.c	2002-12-29 17:05:47 -08:00
+++ b/arch/um/sys-i386/bugs.c	2004-08-24 02:08:18 -07:00
@@ -4,20 +4,21 @@
  */
 
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/signal.h>
+#include <asm/ldt.h>
 #include "kern_util.h"
 #include "user.h"
 #include "sysdep/ptrace.h"
 #include "task.h"
+#include "os.h"
 
 #define MAXTOKEN 64
 
 /* Set during early boot */
-int cpu_has_cmov = 1;
-int cpu_has_xmm = 0;
+int host_has_cmov = 1;
+int host_has_xmm = 0;
 
 static char token(int fd, char *buf, int len, char stop)
 {
@@ -27,13 +28,15 @@
 	ptr = buf;
 	end = &buf[len];
 	do {
-		n = read(fd, ptr, sizeof(*ptr));
+		n = os_read_file(fd, ptr, sizeof(*ptr));
 		c = *ptr++;
-		if(n == 0) return(0);
-		else if(n != sizeof(*ptr)){
-			printk("Reading /proc/cpuinfo failed, "
-			       "errno = %d\n", errno);
-			return(-errno);
+		if(n != sizeof(*ptr)){
+			if(n == 0) return(0);
+			printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
+			if(n < 0)
+				return(n);
+			else
+				return(-EIO);
 		}
 	} while((c != '\n') && (c != stop) && (ptr < end));
 
@@ -45,45 +48,79 @@
 	return(c);
 }
 
-static int check_cpu_feature(char *feature, int *have_it)
+static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
 {
-	char buf[MAXTOKEN], c;
-	int fd, len = sizeof(buf)/sizeof(buf[0]), n;
-
-	printk("Checking for host processor %s support...", feature);
-	fd = open("/proc/cpuinfo", O_RDONLY);
-	if(fd < 0){
-		printk("Couldn't open /proc/cpuinfo, errno = %d\n", errno);
-		return(0);
-	}
+	int n;
+	char c;
 
-	*have_it = 0;
-	buf[len - 1] = '\0';
+	scratch[len - 1] = '\0';
 	while(1){
-		c = token(fd, buf, len - 1, ':');
-		if(c <= 0) goto out;
+		c = token(fd, scratch, len - 1, ':');
+		if(c <= 0)
+			return(0);
 		else if(c != ':'){
 			printk("Failed to find ':' in /proc/cpuinfo\n");
-			goto out;
+			return(0);
 		}
 
-		if(!strncmp(buf, "flags", strlen("flags"))) break;
+		if(!strncmp(scratch, key, strlen(key)))
+			return(1);
 
 		do {
-			n = read(fd, &c, sizeof(c));
+			n = os_read_file(fd, &c, sizeof(c));
 			if(n != sizeof(c)){
 				printk("Failed to find newline in "
-				       "/proc/cpuinfo, n = %d, errno = %d\n",
-				       n, errno);
-				goto out;
+				       "/proc/cpuinfo, err = %d\n", -n);
+				return(0);
 			}
 		} while(c != '\n');
 	}
+	return(0);
+}
+
+int cpu_feature(char *what, char *buf, int len)
+{
+	int fd, ret = 0;
+
+	fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+		return(0);
+	}
+
+	if(!find_cpuinfo_line(fd, what, buf, len)){
+		printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
+		goto out_close;
+	}
+
+	token(fd, buf, len, '\n');
+	ret = 1;
+
+ out_close:
+	os_close_file(fd);
+	return(ret);
+}
+
+static int check_cpu_flag(char *feature, int *have_it)
+{
+	char buf[MAXTOKEN], c;
+	int fd, len = sizeof(buf)/sizeof(buf[0]);
+
+	printk("Checking for host processor %s support...", feature);
+	fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+		return(0);
+	}
+
+	*have_it = 0;
+	if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0])))
+		goto out;
 
 	c = token(fd, buf, len - 1, ' ');
 	if(c < 0) goto out;
 	else if(c != ' '){
-		printk("Failed to find ':' in /proc/cpuinfo\n");
+		printk("Failed to find ' ' in /proc/cpuinfo\n");
 		goto out;
 	}
 
@@ -100,21 +137,48 @@
  out:
 	if(*have_it == 0) printk("No\n");
 	else if(*have_it == 1) printk("Yes\n");
-	close(fd);
+	os_close_file(fd);
 	return(1);
 }
 
+#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
+       * for some people.
+       */
+static void disable_lcall(void)
+{
+	struct modify_ldt_ldt_s ldt;
+	int err;
+
+	bzero(&ldt, sizeof(ldt));
+	ldt.entry_number = 7;
+	ldt.base_addr = 0;
+	ldt.limit = 0;
+	err = modify_ldt(1, &ldt, sizeof(ldt));
+	if(err)
+		printk("Failed to disable lcall7 - errno = %d\n", errno);
+}
+#endif
+
+void arch_init_thread(void)
+{
+#if 0
+	disable_lcall();
+#endif
+}
+
 void arch_check_bugs(void)
 {
 	int have_it;
 
-	if(access("/proc/cpuinfo", R_OK)){
+	if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){
 		printk("/proc/cpuinfo not available - skipping CPU capability "
 		       "checks\n");
 		return;
 	}
-	if(check_cpu_feature("cmov", &have_it)) cpu_has_cmov = have_it;
-	if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it;
+	if(check_cpu_flag("cmov", &have_it))
+		host_has_cmov = have_it;
+	if(check_cpu_flag("xmm", &have_it))
+		host_has_xmm = have_it;
 }
 
 int arch_handle_signal(int sig, union uml_pt_regs *regs)
@@ -130,18 +194,18 @@
 	if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40))
 		return(0);
 
-	if(cpu_has_cmov == 0)
+	if(host_has_cmov == 0)
 		panic("SIGILL caused by cmov, which this processor doesn't "
 		      "implement, boot a filesystem compiled for older "
 		      "processors");
-	else if(cpu_has_cmov == 1)
+	else if(host_has_cmov == 1)
 		panic("SIGILL caused by cmov, which this processor claims to "
 		      "implement");
-	else if(cpu_has_cmov == -1)
+	else if(host_has_cmov == -1)
 		panic("SIGILL caused by cmov, couldn't tell if this processor "
 		      "implements it, boot a filesystem compiled for older "
 		      "processors");
-	else panic("Bad value for cpu_has_cmov (%d)", cpu_has_cmov);
+	else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
 	return(0);
 }
 
diff -Nru a/arch/um/sys-i386/extable.c b/arch/um/sys-i386/extable.c
--- a/arch/um/sys-i386/extable.c	2003-01-16 07:41:52 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,30 +0,0 @@
-/*
- * linux/arch/i386/mm/extable.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
-	       const struct exception_table_entry *last,
-	       unsigned long value)
-{
-        while (first <= last) {
-		const struct exception_table_entry *mid;
-		long diff;
-
-		mid = (last - first) / 2 + first;
-		diff = mid->insn - value;
-                if (diff == 0)
-                        return mid;
-                else if (diff < 0)
-                        first = mid+1;
-                else
-                        last = mid-1;
-        }
-        return NULL;
-}
diff -Nru a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c
--- a/arch/um/sys-i386/fault.c	2003-01-16 07:44:17 -08:00
+++ b/arch/um/sys-i386/fault.c	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,16 +7,24 @@
 #include "sysdep/ptrace.h"
 #include "sysdep/sigcontext.h"
 
-extern unsigned long search_exception_table(unsigned long addr);
+/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
+struct exception_table_entry
+{
+	unsigned long insn;
+	unsigned long fixup;
+};
 
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
+/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
 int arch_fixup(unsigned long address, void *sc_ptr)
 {
 	struct sigcontext *sc = sc_ptr;
-	unsigned long fixup;
+	const struct exception_table_entry *fixup;
 
 	fixup = search_exception_tables(address);
 	if(fixup != 0){
-		sc->eip = fixup;
+		sc->eip = fixup->fixup;
 		return(1);
 	}
 	return(0);
diff -Nru a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
--- a/arch/um/sys-i386/ptrace_user.c	2002-11-20 20:04:11 -08:00
+++ b/arch/um/sys-i386/ptrace_user.c	2004-08-24 02:08:18 -07:00
@@ -39,10 +39,10 @@
 	nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
 	for(i = 0; i < nregs; i++){
 		if((i == 4) || (i == 5)) continue;
-		if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
+		if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i],
 			  regs[i]) < 0)
-			printk("write_debugregs - ptrace failed, "
-			       "errno = %d\n", errno);
+			printk("write_debugregs - ptrace failed on "
+			       "register %d, errno = %d\n", errno);
 	}
 }
 
@@ -54,7 +54,7 @@
 	dummy = NULL;
 	nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
 	for(i = 0; i < nregs; i++){
-		regs[i] = ptrace(PTRACE_PEEKUSR, pid, 
+		regs[i] = ptrace(PTRACE_PEEKUSER, pid,
 				 &dummy->u_debugreg[i], 0);
 	}
 }
diff -Nru a/arch/um/sys-i386/time.c b/arch/um/sys-i386/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/sys-i386/time.c	2004-08-24 11:13:14 -07:00
@@ -0,0 +1,24 @@
+/*
+ * sys-i386/time.c
+ * Created 		25.9.2002	Sapan Bhatia
+ *
+ */
+
+unsigned long long time_stamp(void)
+{
+	unsigned long low, high;
+
+	asm("rdtsc" : "=a" (low), "=d" (high));
+	return((((unsigned long long) high) << 32) + low);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile
--- a/arch/um/sys-i386/util/Makefile	2004-08-10 12:42:40 -07:00
+++ b/arch/um/sys-i386/util/Makefile	2004-08-24 02:08:18 -07:00
@@ -1,15 +1,11 @@
 
-hostprogs-y	:= mk_sc
-always		:= $(hostprogs-y) mk_thread
-targets		:= mk_thread_kern.o mk_thread_user.o
+hostprogs-y	:= mk_sc mk_thread
+always		:= $(hostprogs-y)
 
-mk_sc-objs	:= mk_sc.o
+mk_thread-objs	:= mk_thread_kern.o mk_thread_user.o
 
-$(obj)/mk_thread : $(obj)/mk_thread_kern.o $(obj)/mk_thread_user.o
-	$(CC) $(CFLAGS) -o $@ $^
-
-$(obj)/mk_thread_user.o : $(src)/mk_thread_user.c
-	$(CC) $(USER_CFLAGS) -c -o $@ $<
+HOSTCFLAGS_mk_thread_kern.o	:= $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_thread_user.o	:= $(USER_CFLAGS)
 
 clean :
 	$(RM) -f $(build-targets)
diff -Nru a/arch/um/sys-i386/util/mk_sc.c b/arch/um/sys-i386/util/mk_sc.c
--- a/arch/um/sys-i386/util/mk_sc.c	2002-09-06 10:29:29 -07:00
+++ b/arch/um/sys-i386/util/mk_sc.c	2004-08-24 02:08:18 -07:00
@@ -38,6 +38,7 @@
   SC_OFFSET("SC_ERR", err);
   SC_OFFSET("SC_CR2", cr2);
   SC_OFFSET("SC_FPSTATE", fpstate);
+  SC_OFFSET("SC_SIGMASK", oldmask);
   SC_FP_OFFSET("SC_FP_CW", cw);
   SC_FP_OFFSET("SC_FP_SW", sw);
   SC_FP_OFFSET("SC_FP_TAG", tag);
diff -Nru a/arch/um/sys-ia64/Makefile b/arch/um/sys-ia64/Makefile
--- a/arch/um/sys-ia64/Makefile	2002-12-14 04:38:56 -08:00
+++ b/arch/um/sys-ia64/Makefile	2004-08-24 02:08:18 -07:00
@@ -7,18 +7,5 @@
 $(OBJ): $(OBJS)
 	rm -f $@
 	$(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
-clean:
-	rm -f $(OBJS)
 
-fastdep:
-
-archmrproper:
-
-archclean:
-	rm -f link.ld
-	@$(MAKEBOOT) clean
-
-archdep:
-	@$(MAKEBOOT) dep
-
-modules:
+clean-files := $(OBJS) link.ld
diff -Nru a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
--- a/arch/um/sys-ppc/Makefile	2003-06-03 22:56:33 -07:00
+++ b/arch/um/sys-ppc/Makefile	2004-08-24 02:08:18 -07:00
@@ -66,13 +66,4 @@
 	$(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
 	rm -f asm
 
-clean:
-	rm -f $(OBJS)
-	rm -f ppc_defs.h
-	rm -f checksum.S semaphore.c mk_defs.c
-
-fastdep:
-
-dep:
-
-modules:
+clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c
diff -Nru a/arch/um/uml.lds.S b/arch/um/uml.lds.S
--- a/arch/um/uml.lds.S	2003-02-05 08:34:33 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,92 +0,0 @@
-#include <asm-generic/vmlinux.lds.h>
-	
-OUTPUT_FORMAT(ELF_FORMAT)
-OUTPUT_ARCH(ELF_ARCH)
-ENTRY(_start)
-jiffies = jiffies_64;
-
-SECTIONS
-{
-  . = START + SIZEOF_HEADERS;
-
-  . = ALIGN(4096);
-  __binary_start = .;
-#ifdef MODE_TT
-  .thread_private : {
-    __start_thread_private = .;
-    errno = .;
-    . += 4;
-    arch/um/kernel/tt/unmap_fin.o (.data)
-    __end_thread_private = .;
-  }
-  . = ALIGN(4096);
-  .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
-#endif
-
-  . = ALIGN(4096);		/* Init code and data */
-  _stext = .;
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  . = ALIGN(4096);
-  .text      :
-  {
-    *(.text)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-    *(.gnu.linkonce.t*)
-  }
-
-  #include "asm/common.lds.S"
-
-  .data.init : { *(.data.init) }
-  .data    :
-  {
-    . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
-    *(.data.init_task)
-    *(.data)
-    *(.gnu.linkonce.d*)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  .ctors         :
-  {
-    *(.ctors)
-  }
-  .dtors         :
-  {
-    *(.dtors)
-  }
-
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-  . = ALIGN(0x1000);
-  .sbss      : 
-  {
-   __bss_start = .;
-   PROVIDE(_bss_start = .);
-   *(.sbss) 
-   *(.scommon) 
-  }
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  }
-  _end = . ;
-  PROVIDE (end = .);
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
diff -Nru a/arch/um/util/Makefile b/arch/um/util/Makefile
--- a/arch/um/util/Makefile	2003-03-10 13:03:33 -08:00
+++ b/arch/um/util/Makefile	2004-08-24 02:08:22 -07:00
@@ -1,23 +1,8 @@
-always		:= mk_task mk_constants
-targets		:= mk_task_user.o mk_task_kern.o \
-		   mk_constants_user.o mk_constants_kern.o
+hostprogs-y		:= mk_task mk_constants
+always			:= $(hostprogs-y)
 
-$(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o
-	$(CC) -o $@ $^
+mk_task-objs		:= mk_task_user.o mk_task_kern.o
+mk_constants-objs	:= mk_constants_user.o mk_constants_kern.o
 
-$(obj)/mk_task_user.o: $(src)/mk_task_user.c
-	$(CC) -o $@ -c $< 
-
-$(obj)/mk_constants : $(obj)/mk_constants_user.o $(obj)/mk_constants_kern.o
-	$(CC) -o $@ $^
-
-$(obj)/mk_constants_user.o : $(src)/mk_constants_user.c
-	$(CC) -c $< -o $@
-
-$(obj)/mk_constants_kern.o : $(src)/mk_constants_kern.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-clean:
-	$(RM) $(build-targets)
-
-archmrproper:
+HOSTCFLAGS_mk_task_kern.o	:= $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_constants_kern.o	:= $(CFLAGS) $(CPPFLAGS)
diff -Nru a/arch/um/util/mk_constants_kern.c b/arch/um/util/mk_constants_kern.c
--- a/arch/um/util/mk_constants_kern.c	2002-11-21 10:13:43 -08:00
+++ b/arch/um/util/mk_constants_kern.c	2004-08-24 02:08:18 -07:00
@@ -1,5 +1,6 @@
 #include "linux/kernel.h"
 #include "linux/stringify.h"
+#include "linux/time.h"
 #include "asm/page.h"
 
 extern void print_head(void);
@@ -11,6 +12,7 @@
 {
   print_head();
   print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
+
   print_constant_str("UM_KERN_EMERG", KERN_EMERG);
   print_constant_str("UM_KERN_ALERT", KERN_ALERT);
   print_constant_str("UM_KERN_CRIT", KERN_CRIT);
@@ -19,6 +21,8 @@
   print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
   print_constant_str("UM_KERN_INFO", KERN_INFO);
   print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
+
+  print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC);
   print_tail();
   return(0);
 }
diff -Nru a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
--- a/arch/v850/kernel/setup.c	2004-06-27 00:19:38 -07:00
+++ b/arch/v850/kernel/setup.c	2004-08-24 11:05:57 -07:00
@@ -280,8 +280,8 @@
 #if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1))
 #error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it)
 #endif
-
-	free_area_init_node (0, NODE_DATA(0), 0, zones_size,
+	NODE_DATA(0)->node_mem_map = NULL;
+	free_area_init_node (0, NODE_DATA(0), zones_size,
 			     ADDR_TO_PAGE (PAGE_OFFSET), 0);
 	mem_map = NODE_DATA(0)->node_mem_map;
 }
diff -Nru a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
--- a/arch/v850/kernel/signal.c	2003-02-17 18:41:09 -08:00
+++ b/arch/v850/kernel/signal.c	2004-08-25 17:37:26 -07:00
@@ -344,9 +344,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -421,9 +419,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
diff -Nru a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
--- a/arch/v850/kernel/time.c	2004-06-24 01:55:53 -07:00
+++ b/arch/v850/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -40,24 +40,6 @@
 	return (unsigned long long)jiffies * (1000000000 / HZ);
 }
 
-static inline void do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		if (pc < prof_len)
-			++prof_buffer[pc];
-		else
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			++prof_buffer[prof_len-1];
-	}
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -74,10 +56,7 @@
 	  mach_tick ();
 
 	do_timer (regs);
-
-	if (! user_mode (regs))
-		do_profile (regs->pc);
-
+	profile_tick(CPU_PROFILING, regs);
 #if 0
 	/*
 	 * If we have an externally synchronized Linux clock, then update
diff -Nru a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
--- a/arch/v850/kernel/vmlinux.lds.S	2004-06-24 01:20:36 -07:00
+++ b/arch/v850/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -111,9 +111,6 @@
 			*(.init.setup)	/* 2.5 convention */		      \
 			*(.setup.init)	/* 2.4 convention */		      \
 		___setup_end = . ;					      \
-		___start___param = . ;					      \
-			*(__param)					      \
-		___stop___param = . ;					      \
 		___initcall_start = . ;					      \
 			*(.initcall.init)				      \
 			*(.initcall1.init)				      \
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	2004-08-15 12:45:19 -07:00
+++ b/arch/x86_64/Kconfig	2004-08-24 02:08:31 -07:00
@@ -347,6 +347,17 @@
 	depends on PCI
 	select ACPI_BOOT
 
+config UNORDERED_IO
+       bool "Unordered IO mapping access"
+       depends on EXPERIMENTAL
+       select UNORDERED_IO
+       help
+         Use unordered stores to access IO memory mappings in device drivers.
+	 Still very experimental. When a driver works on IA64/ppc64/pa-risc it should
+	 work with this option, but it makes the drivers behave differently
+	 from i386. Requires that the driver writer used memory barriers
+	 properly.
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
diff -Nru a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
--- a/arch/x86_64/Kconfig.debug	2004-08-15 12:45:41 -07:00
+++ b/arch/x86_64/Kconfig.debug	2004-08-24 02:08:10 -07:00
@@ -18,6 +18,18 @@
 	  Fill __init and __initdata at the end of boot. This helps debugging
 	  illegal uses of __init and __initdata after initialization.
 
+config SCHEDSTATS
+	bool "Collect scheduler statistics"
+	depends on DEBUG_KERNEL && PROC_FS
+	help
+	  If you say Y here, additional code will be inserted into the
+	  scheduler and related routines to collect statistics about
+	  scheduler behavior and provide them in /proc/schedstat.  These
+	  stats may be useful for both tuning and debugging the scheduler
+	  If you aren't debugging the scheduler or trying to tune a specific
+	  application, you can say N to avoid the very slight overhead
+	  this adds.
+
 config FRAME_POINTER
        bool "Compile the kernel with frame pointers"
        help
diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile
--- a/arch/x86_64/Makefile	2004-08-22 13:24:25 -07:00
+++ b/arch/x86_64/Makefile	2004-08-24 02:08:31 -07:00
@@ -77,6 +77,7 @@
 all: bzImage
 
 BOOTIMAGE                     := arch/x86_64/boot/bzImage
+KBUILD_IMAGE                  := $(BOOTIMAGE)
 
 bzImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
diff -Nru a/arch/x86_64/defconfig b/arch/x86_64/defconfig
--- a/arch/x86_64/defconfig	2004-08-09 16:41:37 -07:00
+++ b/arch/x86_64/defconfig	2004-08-24 02:08:31 -07:00
@@ -17,7 +17,6 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
@@ -29,12 +28,13 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=18
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
@@ -104,8 +104,8 @@
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_THERMAL=y
 # CONFIG_ACPI_ASUS is not set
-CONFIG_ACPI_TOSHIBA=y
-CONFIG_ACPI_DEBUG=y
+# CONFIG_ACPI_TOSHIBA is not set
+# CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_BUS=y
 CONFIG_ACPI_EC=y
 CONFIG_ACPI_POWER=y
@@ -115,7 +115,23 @@
 #
 # CPU Frequency scaling
 #
-# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_PROC_INTF=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_24_API is not set
+CONFIG_CPU_FREQ_TABLE=y
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_POWERNOW_K8=y
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+CONFIG_X86_ACPI_CPUFREQ=y
+CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
 
 #
 # Bus options (PCI etc.)
@@ -123,10 +139,27 @@
 CONFIG_PCI=y
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
+CONFIG_UNORDERED_IO=y
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
 
 #
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_ACPI is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
 # Executable file formats / Emulations
 #
 CONFIG_BINFMT_ELF=y
@@ -144,6 +177,9 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -171,7 +207,7 @@
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -186,10 +222,10 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA is not set
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -234,7 +270,7 @@
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -273,16 +309,24 @@
 # SCSI low-level drivers
 #
 CONFIG_BLK_DEV_3W_XXXX_RAID=y
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
+CONFIG_SCSI_AIC79XX=y
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=2000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
 # CONFIG_SCSI_MEGARAID is not set
 CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_SATA_SVW is not set
 CONFIG_SCSI_ATA_PIIX=y
+# CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_SX4 is not set
 # CONFIG_SCSI_SATA_SIL is not set
@@ -290,7 +334,6 @@
 CONFIG_SCSI_SATA_VIA=y
 # CONFIG_SCSI_SATA_VITESSE is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
@@ -392,6 +435,7 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -431,8 +475,7 @@
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
-CONFIG_AMD8111_ETH=y
-# CONFIG_AMD8111E_NAPI is not set
+# CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
 CONFIG_FORCEDETH=y
@@ -442,16 +485,13 @@
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
-CONFIG_8139CP=m
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -602,6 +642,9 @@
 # CONFIG_DRM is not set
 # CONFIG_MWAVE is not set
 CONFIG_RAW_DRIVER=y
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+CONFIG_HPET_MMAP=y
 CONFIG_MAX_RAW_DEVS=256
 CONFIG_HANGCHECK_TIMER=y
 
@@ -611,6 +654,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 # CONFIG_IBM_ASM is not set
@@ -703,17 +751,8 @@
 # CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
-CONFIG_USB_PRINTER=y
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_STORAGE is not set
 
 #
 # USB Human Interface Devices (HID)
@@ -830,7 +869,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -856,6 +896,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -909,10 +950,11 @@
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_INIT_DEBUG is not set
+CONFIG_INIT_DEBUG=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_FRAME_POINTER is not set
-# CONFIG_IOMMU_DEBUG is not set
+CONFIG_IOMMU_DEBUG=y
+# CONFIG_IOMMU_LEAK is not set
 
 #
 # Security options
@@ -927,5 +969,6 @@
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
--- a/arch/x86_64/ia32/ia32_binfmt.c	2004-05-22 14:56:29 -07:00
+++ b/arch/x86_64/ia32/ia32_binfmt.c	2004-08-27 00:02:34 -07:00
@@ -301,6 +301,9 @@
 
 #define elf_addr_t __u32
 
+#undef TASK_SIZE
+#define TASK_SIZE 0xffffffff
+
 static void elf32_init(struct pt_regs *);
 
 #include "../../../fs/binfmt_elf.c" 
@@ -365,7 +368,7 @@
  		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? 
  			PAGE_COPY_EXEC : PAGE_COPY;
 		insert_vm_struct(mm, mpnt);
-		mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
 	} 
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
diff -Nru a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c
--- a/arch/x86_64/ia32/ia32_ioctl.c	2004-05-30 12:49:35 -07:00
+++ b/arch/x86_64/ia32/ia32_ioctl.c	2004-08-24 02:08:31 -07:00
@@ -171,23 +171,8 @@
 COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS)
 COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
 COMPATIBLE_IOCTL(BLKRASET)
-COMPATIBLE_IOCTL(BLKFRASET)
 COMPATIBLE_IOCTL(0x4B50)   /* KDGHWCLK - not in the kernel, but don't complain */
 COMPATIBLE_IOCTL(0x4B51)   /* KDSHWCLK - not in the kernel, but don't complain */
-COMPATIBLE_IOCTL(RTC_AIE_ON)
-COMPATIBLE_IOCTL(RTC_AIE_OFF)
-COMPATIBLE_IOCTL(RTC_UIE_ON)
-COMPATIBLE_IOCTL(RTC_UIE_OFF)
-COMPATIBLE_IOCTL(RTC_PIE_ON)
-COMPATIBLE_IOCTL(RTC_PIE_OFF)
-COMPATIBLE_IOCTL(RTC_WIE_ON)
-COMPATIBLE_IOCTL(RTC_WIE_OFF)
-COMPATIBLE_IOCTL(RTC_ALM_SET)
-COMPATIBLE_IOCTL(RTC_ALM_READ)
-COMPATIBLE_IOCTL(RTC_RD_TIME)
-COMPATIBLE_IOCTL(RTC_SET_TIME)
-COMPATIBLE_IOCTL(RTC_WKALM_SET)
-COMPATIBLE_IOCTL(RTC_WKALM_RD)
 COMPATIBLE_IOCTL(FIOQSIZE)
 
 /* And these ioctls need translation */
diff -Nru a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
--- a/arch/x86_64/ia32/ia32_signal.c	2004-07-13 05:58:13 -07:00
+++ b/arch/x86_64/ia32/ia32_signal.c	2004-08-25 17:37:26 -07:00
@@ -115,7 +115,8 @@
 }
 
 asmlinkage long
-sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs regs)
+sys32_sigsuspend(int history0, int history1, old_sigset_t mask,
+		 struct pt_regs *regs)
 {
 	sigset_t saveset;
 
@@ -126,11 +127,11 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs.rax = -EINTR;
+	regs->rax = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&regs, &saveset))
+		if (do_signal(regs, &saveset))
 			return -EINTR;
 	}
 }
@@ -138,7 +139,7 @@
 asmlinkage long
 sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
 		  stack_ia32_t __user *uoss_ptr, 
-		  struct pt_regs regs)
+		  struct pt_regs *regs)
 {
 	stack_t uss,uoss; 
 	int ret;
@@ -155,7 +156,7 @@
 	}
 	seg = get_fs(); 
 	set_fs(KERNEL_DS); 
-	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp);
+	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->rsp);
 	set_fs(seg); 
 	if (ret >= 0 && uoss_ptr)  {
 		if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) ||
@@ -274,9 +275,9 @@
 	return 1;
 }
 
-asmlinkage long sys32_sigreturn(struct pt_regs regs)
+asmlinkage long sys32_sigreturn(struct pt_regs *regs)
 {
-	struct sigframe __user *frame = (struct sigframe __user *)(regs.rsp-8);
+	struct sigframe __user *frame = (struct sigframe __user *)(regs->rsp-8);
 	sigset_t set;
 	unsigned int eax;
 
@@ -294,20 +295,23 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	
-	if (ia32_restore_sigcontext(&regs, &frame->sc, &eax))
+	if (ia32_restore_sigcontext(regs, &frame->sc, &eax))
 		goto badframe;
 	return eax;
 
 badframe:
-	signal_fault(&regs, frame, "32bit sigreturn"); 
+	signal_fault(regs, frame, "32bit sigreturn");
 	return 0;
 }	
 
-asmlinkage long sys32_rt_sigreturn(struct pt_regs regs)
+asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
 {
-	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs.rsp - 4);
+	struct rt_sigframe __user *frame;
 	sigset_t set;
 	unsigned int eax;
+	struct pt_regs tregs;
+
+	frame = (struct rt_sigframe __user *)(regs->rsp - 4);
 
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -320,16 +324,17 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	
-	if (ia32_restore_sigcontext(&regs, &frame->uc.uc_mcontext, &eax))
+	if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax))
 		goto badframe;
 
-	if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, regs) == -EFAULT)
+	tregs = *regs;
+	if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
 		goto badframe;
 
 	return eax;
 
 badframe:
-	signal_fault(&regs,frame,"32bit rt sigreturn");
+	signal_fault(regs,frame,"32bit rt sigreturn");
 	return 0;
 }	
 
@@ -494,9 +499,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	signal_fault(regs,frame,"32bit signal deliver");
+	force_sigsegv(sig, current);
 }
 
 void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -590,8 +593,6 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	signal_fault(regs, frame, "32bit rt signal setup"); 
+	force_sigsegv(sig, current);
 }
 
diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
--- a/arch/x86_64/ia32/ia32entry.S	2004-05-30 10:55:21 -07:00
+++ b/arch/x86_64/ia32/ia32entry.S	2004-08-24 02:08:31 -07:00
@@ -270,35 +270,32 @@
 	ret
 	CFI_ENDPROC
 	
-	.macro PTREGSCALL label, func
+	.macro PTREGSCALL label, func, arg
 	.globl \label
 \label:
 	leaq \func(%rip),%rax
+	leaq -ARGOFFSET+8(%rsp),\arg	/* 8 for return address */
 	jmp  ia32_ptregs_common	
 	.endm
 
-	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn
-	PTREGSCALL stub32_sigreturn, sys32_sigreturn
-	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack
-	PTREGSCALL stub32_sigsuspend, sys32_sigsuspend
-	PTREGSCALL stub32_execve, sys32_execve
-	PTREGSCALL stub32_fork, sys_fork
-	PTREGSCALL stub32_clone, sys32_clone
-	PTREGSCALL stub32_vfork, sys_vfork
-	PTREGSCALL stub32_iopl, sys_iopl
-	PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend
+	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
+	PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
+	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
+	PTREGSCALL stub32_sigsuspend, sys32_sigsuspend, %rcx
+	PTREGSCALL stub32_execve, sys32_execve, %rcx
+	PTREGSCALL stub32_fork, sys_fork, %rdi
+	PTREGSCALL stub32_clone, sys32_clone, %rdx
+	PTREGSCALL stub32_vfork, sys_vfork, %rdi
+	PTREGSCALL stub32_iopl, sys_iopl, %rsi
+	PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx
 
 ENTRY(ia32_ptregs_common)
 	CFI_STARTPROC
 	popq %r11
 	SAVE_REST
-	movq %r11, %r15
 	call *%rax
-	movq %r15, %r11
 	RESTORE_REST
-	leaq ia32_sysret(%rip),%r11
-	pushq %r11
-	ret
+	jmp  ia32_sysret	/* misbalances the return cache */
 	CFI_ENDPROC
 
 	.data
@@ -332,7 +329,7 @@
 	.quad sys_getuid16
 	.quad sys_stime		/* stime */		/* 25 */
 	.quad sys32_ptrace	/* ptrace */
-	.quad sys_alarm		/* XXX sign extension??? */ 
+	.quad sys_alarm
 	.quad sys_fstat	/* (old)fstat */
 	.quad sys_pause
 	.quad compat_sys_utime	/* 30 */
@@ -558,7 +555,7 @@
 	.quad sys_fadvise64		/* 250 */
 	.quad quiet_ni_syscall 	/* free_huge_pages */
 	.quad sys_exit_group
-	.quad sys_lookup_dcookie
+	.quad sys32_lookup_dcookie
 	.quad sys_epoll_create
 	.quad sys_epoll_ctl		/* 255 */
 	.quad sys_epoll_wait
diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
--- a/arch/x86_64/ia32/ptrace32.c	2004-05-30 12:49:35 -07:00
+++ b/arch/x86_64/ia32/ptrace32.c	2004-08-24 02:08:31 -07:00
@@ -249,8 +249,8 @@
 	case PTRACE_GETFPREGS:
 	case PTRACE_SETFPXREGS:
 	case PTRACE_GETFPXREGS:
+	case PTRACE_GETEVENTMSG:
 		break;
-		
 	} 
 
 	child = find_target(request, pid, &ret);
@@ -362,6 +362,10 @@
 		ret = 0; 
 		break;
 	}
+
+	case PTRACE_GETEVENTMSG:
+		ret = put_user(child->ptrace_message,(unsigned int __user *)(u64)data);
+		break;
 
 	default:
 		ret = -EINVAL;
diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	2004-08-23 01:15:23 -07:00
+++ b/arch/x86_64/ia32/sys_ia32.c	2004-08-24 02:08:42 -07:00
@@ -1125,7 +1125,7 @@
 } 
 
 asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
-			     compat_uptr_t __user *envp, struct pt_regs regs)
+			     compat_uptr_t __user *envp, struct pt_regs *regs)
 {
 	long error;
 	char * filename;
@@ -1134,21 +1134,21 @@
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		return error;
-	error = compat_do_execve(filename, argv, envp, &regs);
+	error = compat_do_execve(filename, argv, envp, regs);
 	if (error == 0)
 		current->ptrace &= ~PT_DTRACE;
 	putname(filename);
 	return error;
 }
 
-asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs)
+asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
+			    struct pt_regs *regs)
 {
-	void __user *parent_tid = (void __user *)regs.rdx;
-	void __user *child_tid = (void __user *)regs.rdi; 
+	void __user *parent_tid = (void __user *)regs->rdx;
+	void __user *child_tid = (void __user *)regs->rdi;
 	if (!newsp)
-		newsp = regs.rsp;
-        return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, 
-		    parent_tid, child_tid);
+		newsp = regs->rsp;
+        return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
 
 /*
@@ -1336,6 +1336,12 @@
 	} 
 	return -ENOSYS;
 } 
+
+long sys32_lookup_dcookie(u32 addr_low, u32 addr_high,
+			  char __user * buf, size_t len)
+{
+	return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
+}
 
 cond_syscall(sys32_ipc)
 
diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
--- a/arch/x86_64/kernel/Makefile	2004-08-15 11:20:44 -07:00
+++ b/arch/x86_64/kernel/Makefile	2004-08-24 02:08:09 -07:00
@@ -25,7 +25,6 @@
 obj-$(CONFIG_GART_IOMMU)	+= pci-gart.o aperture.o
 obj-$(CONFIG_DUMMY_IOMMU)	+= pci-nommu.o pci-dma.o
 obj-$(CONFIG_SWIOTLB)		+= swiotlb.o
-obj-$(CONFIG_SCHED_SMT)		+= domain.o
 
 obj-$(CONFIG_MODULES)		+= module.o
 
diff -Nru a/arch/x86_64/kernel/Makefile-HEAD b/arch/x86_64/kernel/Makefile-HEAD
--- a/arch/x86_64/kernel/Makefile-HEAD	2004-08-15 11:20:44 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,38 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y 	:= head.o head64.o init_task.o vmlinux.lds
-EXTRA_AFLAGS	:= -traditional
-obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
-		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
-		x8664_ksyms.o i387.o syscall.o vsyscall.o \
-		setup64.o bootflag.o e820.o reboot.o warmreboot.o
-obj-y += mce.o
-
-obj-$(CONFIG_MTRR)		+= ../../i386/kernel/cpu/mtrr/
-obj-$(CONFIG_ACPI_BOOT)		+= acpi/
-obj-$(CONFIG_X86_MSR)		+= msr.o
-obj-$(CONFIG_MICROCODE)		+= microcode.o
-obj-$(CONFIG_X86_CPUID)		+= cpuid.o
-obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
-obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o  nmi.o
-obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o
-obj-$(CONFIG_PM)		+= suspend.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend_asm.o
-obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
-obj-$(CONFIG_GART_IOMMU)	+= pci-gart.o aperture.o
-obj-$(CONFIG_DUMMY_IOMMU)	+= pci-nommu.o pci-dma.o
-obj-$(CONFIG_SWIOTLB)		+= swiotlb.o
-obj-$(CONFIG_SCHED_SMT)		+= domain.o
-
-obj-$(CONFIG_MODULES)		+= module.o
-
-obj-y				+= topology.o
-
-bootflag-y			+= ../../i386/kernel/bootflag.o
-cpuid-$(subst m,y,$(CONFIG_X86_CPUID))  += ../../i386/kernel/cpuid.o
-topology-y                     += ../../i386/mach-default/topology.o
-swiotlb-$(CONFIG_SWIOTLB)      += ../../ia64/lib/swiotlb.o
-microcode-$(subst m,y,$(CONFIG_MICROCODE))  += ../../i386/kernel/microcode.o
diff -Nru a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
--- a/arch/x86_64/kernel/aperture.c	2004-04-12 10:53:56 -07:00
+++ b/arch/x86_64/kernel/aperture.c	2004-08-24 02:08:31 -07:00
@@ -31,6 +31,8 @@
 int fallback_aper_order __initdata = 1; /* 64MB */
 int fallback_aper_force __initdata = 0; 
 
+int fix_aperture __initdata = 1;
+
 /* This code runs before the PCI subsystem is initialized, so just 
    access the northbridge directly. */
 
@@ -202,7 +204,7 @@
 	u64 aper_base; 
 	int valid_agp = 0;
 
-	if (iommu_aperture_disabled)
+	if (iommu_aperture_disabled || !fix_aperture)
 		return;
 
 	printk("Checking aperture...\n"); 
@@ -241,20 +243,15 @@
 		/* Got the aperture from the AGP bridge */
 	} else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
 		   force_iommu ||
-		   valid_agp || 
+		   valid_agp ||
 		   fallback_aper_force) { 
-		/* When there is a AGP bridge in the system assume the
-		   user wants to use the AGP driver too and needs an
-		   aperture.  However this case (AGP but no good
-		   aperture) should only happen with a more broken than
-		   usual BIOS, because it would even break Windows. */
-
-	printk("Your BIOS doesn't leave a aperture memory hole\n");
-	printk("Please enable the IOMMU option in the BIOS setup\n"); 
-		printk("This costs you %d MB of RAM\n", 32 << fallback_aper_order); 
- 
+		printk("Your BIOS doesn't leave a aperture memory hole\n");
+		printk("Please enable the IOMMU option in the BIOS setup\n");
+		printk("This costs you %d MB of RAM\n",
+		       32 << fallback_aper_order);
+
 		aper_order = fallback_aper_order;
-	aper_alloc = allocate_aperture(); 
+		aper_alloc = allocate_aperture();
 		if (!aper_alloc) { 
 			/* Could disable AGP and IOMMU here, but it's probably
 			   not worth it. But the later users cannot deal with
diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
--- a/arch/x86_64/kernel/apic.c	2004-02-26 15:55:11 -08:00
+++ b/arch/x86_64/kernel/apic.c	2004-08-26 23:30:31 -07:00
@@ -836,8 +836,7 @@
 {
 	int cpu = smp_processor_id();
 
-	x86_do_profile(regs);
-
+	profile_tick(CPU_PROFILING, regs);
 	if (--per_cpu(prof_counter, cpu) <= 0) {
 		/*
 		 * The multiplier may have changed since the last time we got
diff -Nru a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig
--- a/arch/x86_64/kernel/cpufreq/Kconfig	2004-07-12 16:14:59 -07:00
+++ b/arch/x86_64/kernel/cpufreq/Kconfig	2004-08-24 02:08:31 -07:00
@@ -46,4 +46,53 @@
 	depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
 	default y
 
+config X86_SPEEDSTEP_CENTRINO
+	tristate "Intel Enhanced SpeedStep"
+	depends on CPU_FREQ_TABLE
+	help
+	  This adds the CPUFreq driver for Enhanced SpeedStep enabled
+	  mobile CPUs.  This means Intel Pentium M (Centrino) CPUs
+	  or 64bit enabled Intel Xeons.
+
+	  For details, take a look at <file:Documentation/cpu-freq/>.
+
+	  If in doubt, say N.
+
+config X86_SPEEDSTEP_CENTRINO_TABLE
+	bool
+	depends on X86_SPEEDSTEP_CENTRINO
+	default y
+
+config X86_SPEEDSTEP_CENTRINO_ACPI
+	bool "Use ACPI tables to decode valid frequency/voltage pairs (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y"))
+	help
+	  Use primarily the information provided in the BIOS ACPI tables
+	  to determine valid CPU frequency and voltage pairings.
+
+	  If in doubt, say Y.
+
+config X86_ACPI_CPUFREQ
+	tristate "ACPI Processor P-States driver"
+	depends on CPU_FREQ_TABLE && ACPI_PROCESSOR
+	help
+	  This driver adds a CPUFreq driver which utilizes the ACPI
+	  Processor Performance States.
+
+	  For details, take a look at <file:Documentation/cpu-freq/>.
+
+	  If in doubt, say N.
+
+config X86_ACPI_CPUFREQ_PROC_INTF
+        bool "/proc/acpi/processor/../performance interface (deprecated)"
+	depends on X86_ACPI_CPUFREQ && PROC_FS
+	help
+	  This enables the deprecated /proc/acpi/processor/../performance
+	  interface. While it is helpful for debugging, the generic,
+	  cross-architecture cpufreq interfaces should be used.
+
+	  If in doubt, say N.
+
 endmenu
+
diff -Nru a/arch/x86_64/kernel/cpufreq/Makefile b/arch/x86_64/kernel/cpufreq/Makefile
--- a/arch/x86_64/kernel/cpufreq/Makefile	2003-10-08 15:38:34 -07:00
+++ b/arch/x86_64/kernel/cpufreq/Makefile	2004-08-24 02:08:31 -07:00
@@ -2,6 +2,12 @@
 # Reuse the i386 cpufreq drivers
 #
 
+SRCDIR := ../../../i386/kernel/cpu/cpufreq
+
 obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
+obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
+obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o
 
-powernow-k8-objs := ../../../i386/kernel/cpu/cpufreq/powernow-k8.o
+powernow-k8-objs := ${SRCDIR}/powernow-k8.o
+speedstep-centrino-objs := ${SRCDIR}/speedstep-centrino.o
+acpi-objs := ${SRCDIR}/acpi.o
diff -Nru a/arch/x86_64/kernel/domain.c b/arch/x86_64/kernel/domain.c
--- a/arch/x86_64/kernel/domain.c	2004-05-15 06:40:13 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,93 +0,0 @@
-#include <linux/init.h>
-#include <linux/sched.h>
-
-/* Don't do any NUMA setup on Opteron right now. They seem to be
-   better off with flat scheduling. This is just for SMT. */
-
-#ifdef CONFIG_SCHED_SMT
-
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		/* Disable SMT NICE for CMP */
-		/* RED-PEN use a generic flag */ 
-		if (cpu_data[i].x86_vendor == X86_VENDOR_AMD) 
-			cpu_domain->flags &= ~SD_SHARE_CPUPOWER; 
-		cpu_domain->span = cpu_sibling_map[i];
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = cpu_possible_map;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	first = last = NULL;
-	/* Set up physical groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_group *cpu = &sched_group_phys[i];
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		cpu->cpumask = cpu_domain->span;
-		/*
-		 * Make each extra sibling increase power by 10% of
-		 * the basic CPU. This is very arbitrary.
-		 */
-		cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
-}
-
-#endif
diff -Nru a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
--- a/arch/x86_64/kernel/early_printk.c	2004-02-18 19:42:41 -08:00
+++ b/arch/x86_64/kernel/early_printk.c	2004-08-26 23:59:59 -07:00
@@ -8,7 +8,7 @@
 /* Simple VGA output */
 
 #ifdef __i386__
-#define VGABASE		__pa(__PAGE_OFFSET + 0xb8000UL)
+#define VGABASE		__pa((void *)(__PAGE_OFFSET + 0xb8000UL))
 #else
 #define VGABASE		0xffffffff800b8000UL
 #endif
@@ -99,18 +99,17 @@
 
 #define DEFAULT_BAUD 9600
 
-static __init void early_serial_init(char *opt)
+static __init void early_serial_init(char *s)
 {
 	unsigned char c; 
 	unsigned divisor;
 	unsigned baud = DEFAULT_BAUD;
-	char *s, *e;
+	char *e;
 
-	if (*opt == ',') 
-		++opt;
+	if (*s == ',')
+		++s;
 
-	s = strsep(&opt, ","); 
-	if (s != NULL) { 
+	if (*s) {
 		unsigned port; 
 		if (!strncmp(s,"0x",2)) {
 			early_serial_base = simple_strtoul(s, &e, 16);
@@ -124,6 +123,9 @@
 				port = 0;
 			early_serial_base = bases[port];
 		}
+		s += strcspn(s, ",");
+		if (*s == ',')
+			s++;
 	}
 
 	outb(0x3, early_serial_base + LCR);	/* 8n1 */
@@ -131,8 +133,7 @@
 	outb(0, early_serial_base + FCR);	/* no fifo */
 	outb(0x3, early_serial_base + MCR);	/* DTR + RTS */
 
-	s = strsep(&opt, ","); 
-	if (s != NULL) { 
+	if (*s) {
 		baud = simple_strtoul(s, &e, 0); 
 		if (baud == 0 || s == e) 
 			baud = DEFAULT_BAUD;
diff -Nru a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
--- a/arch/x86_64/kernel/entry.S	2004-08-23 01:14:58 -07:00
+++ b/arch/x86_64/kernel/entry.S	2004-08-24 02:08:31 -07:00
@@ -324,19 +324,20 @@
  * Certain special system calls that need to save a complete full stack frame.
  */ 								
 	
-	.macro PTREGSCALL label,func
+	.macro PTREGSCALL label,func,arg
 	.globl \label
 \label:
 	leaq	\func(%rip),%rax
+	leaq    -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
 	jmp	ptregscall_common
 	.endm
 
-	PTREGSCALL stub_clone, sys_clone
-	PTREGSCALL stub_fork, sys_fork
-	PTREGSCALL stub_vfork, sys_vfork
-	PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend
-	PTREGSCALL stub_sigaltstack, sys_sigaltstack
-	PTREGSCALL stub_iopl, sys_iopl
+	PTREGSCALL stub_clone, sys_clone, %r8
+	PTREGSCALL stub_fork, sys_fork, %rdi
+	PTREGSCALL stub_vfork, sys_vfork, %rdi
+	PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
+	PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
+	PTREGSCALL stub_iopl, sys_iopl, %rsi
 
 ENTRY(ptregscall_common)
 	CFI_STARTPROC
@@ -386,6 +387,7 @@
 	CFI_STARTPROC
 	addq $8, %rsp		
 	SAVE_REST
+	movq %rsp,%rdi
 	FIXUP_TOP_OF_STACK %r11
 	call sys_rt_sigreturn
 	movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
diff -Nru a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c
--- a/arch/x86_64/kernel/ioport.c	2004-03-08 06:23:47 -08:00
+++ b/arch/x86_64/kernel/ioport.c	2004-08-24 02:08:31 -07:00
@@ -83,9 +83,9 @@
  * code.
  */
 
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs)
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
 {
-	unsigned int old = (regs.eflags >> 12) & 3;
+	unsigned int old = (regs->eflags >> 12) & 3;
 
 	if (level > 3)
 		return -EINVAL;
@@ -94,6 +94,6 @@
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
-	regs.eflags = (regs.eflags &~ 0x3000UL) | (level << 12);
+	regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
 	return 0;
 }
diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
--- a/arch/x86_64/kernel/irq.c	2004-07-13 06:08:49 -07:00
+++ b/arch/x86_64/kernel/irq.c	2004-08-26 23:30:30 -07:00
@@ -862,31 +862,6 @@
 
 #endif
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file,
-					const char __user *buffer,
-					unsigned long count, void *data)
-{
-	unsigned long full_count = count, err;
-	cpumask_t new_value, *mask = (cpumask_t *)data;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -922,26 +897,15 @@
 #endif
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", NULL);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-	    return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
@@ -949,4 +913,3 @@
 	for (i = 0; i < NR_IRQS; i++)
 		register_irq_proc(i);
 }
-
diff -Nru a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
--- a/arch/x86_64/kernel/mce.c	2004-08-23 01:15:14 -07:00
+++ b/arch/x86_64/kernel/mce.c	2004-08-24 02:08:31 -07:00
@@ -24,7 +24,8 @@
 #define MISC_MCELOG_MINOR 227
 #define NR_BANKS 5
 
-static int mce_disabled __initdata;
+static int mce_dont_init;
+
 /* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic,
    3: never panic or exit (for testing only) */
 static int tolerant = 1;
@@ -113,9 +114,8 @@
 
 static int mce_available(struct cpuinfo_x86 *c)
 {
-	return !mce_disabled && 
-		test_bit(X86_FEATURE_MCE, &c->x86_capability) &&
-		test_bit(X86_FEATURE_MCA, &c->x86_capability);
+	return test_bit(X86_FEATURE_MCE, &c->x86_capability) &&
+	       test_bit(X86_FEATURE_MCA, &c->x86_capability);
 }
 
 /* 
@@ -127,8 +127,9 @@
 	struct mce m, panicm;
 	int nowayout = (tolerant < 1); 
 	int kill_it = 0;
-	u64 mcestart;
+	u64 mcestart = 0;
 	int i;
+	int panicm_found = 0;
 
 	if (regs)
 		notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL);
@@ -138,17 +139,11 @@
 	memset(&m, 0, sizeof(struct mce));
 	m.cpu = hard_smp_processor_id();
 	rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
-	if (!regs && (m.mcgstatus & MCG_STATUS_MCIP))
-		return;
 	if (!(m.mcgstatus & MCG_STATUS_RIPV))
 		kill_it = 1;
-	if (regs) {
-		m.rip = regs->rip;
-		m.cs = regs->cs;
-	}
 	
 	rdtscll(mcestart);
-	mb();
+	barrier();
 
 	for (i = 0; i < banks; i++) {
 		if (!bank[i])
@@ -156,52 +151,62 @@
 		
 		m.misc = 0; 
 		m.addr = 0;
+		m.bank = i;
+		m.tsc = 0;
 
 		rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status);
 		if ((m.status & MCI_STATUS_VAL) == 0)
 			continue;
-		/* Should be implied by the banks check above, but
-		   check it anyways */
-		if ((m.status & MCI_STATUS_EN) == 0)
-			continue;
 
-		/* Did this bank cause the exception? */
-		/* Assume that the bank with uncorrectable errors did it,
-		   and that there is only a single one. */
-		if (m.status & MCI_STATUS_UC) {
-			panicm = m;
-		} else {
-			m.rip = 0;
-			m.cs = 0;
+		if (m.status & MCI_STATUS_EN) {
+			/* In theory _OVER could be a nowayout too, but
+			   assume any overflowed errors were no fatal. */
+			nowayout |= !!(m.status & MCI_STATUS_PCC);
+			kill_it |= !!(m.status & MCI_STATUS_UC);
 		}
 
-		/* In theory _OVER could be a nowayout too, but
-		   assume any overflowed errors were no fatal. */
-		nowayout |= !!(m.status & MCI_STATUS_PCC);
-		kill_it |= !!(m.status & MCI_STATUS_UC);
-		m.bank = i;
-
 		if (m.status & MCI_STATUS_MISCV)
 			rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc);
 		if (m.status & MCI_STATUS_ADDRV)
 			rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
 
-		rdtscll(m.tsc);
+		if (regs && (m.mcgstatus & MCG_STATUS_RIPV)) {
+			m.rip = regs->rip;
+			m.cs = regs->cs;
+		} else {
+			m.rip = 0;
+			m.cs = 0;
+		}
+
+		if (error_code != -1)
+			rdtscll(m.tsc);
 		wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0);
 		mce_log(&m);
+
+		/* Did this bank cause the exception? */
+		/* Assume that the bank with uncorrectable errors did it,
+		   and that there is only a single one. */
+		if ((m.status & MCI_STATUS_UC) && (m.status & MCI_STATUS_EN)) {
+			panicm = m;
+			panicm_found = 1;
+		}
 	}
-	wrmsrl(MSR_IA32_MCG_STATUS, 0);
 
 	/* Never do anything final in the polling timer */
 	if (!regs)
-		return;
+		goto out;
+
+	/* If we didn't find an uncorrectable error, pick
+	   the last one (shouldn't happen, just being safe). */
+	if (!panicm_found)
+		panicm = m;
 	if (nowayout)
-		mce_panic("Machine check", &m, mcestart);
+		mce_panic("Machine check", &panicm, mcestart);
 	if (kill_it) {
 		int user_space = 0;
 
 		if (m.mcgstatus & MCG_STATUS_RIPV)
-			user_space = m.rip && (m.cs & 3);
+			user_space = panicm.rip && (panicm.cs & 3);
 		
 		/* When the machine was in user space and the CPU didn't get
 		   confused it's normally not necessary to panic, unless you 
@@ -214,18 +219,15 @@
 		    (unsigned)current->pid <= 1)
 			mce_panic("Uncorrected machine check", &panicm, mcestart);
 
-		/* do_exit takes an awful lot of locks and has as slight risk 
-		   of deadlocking. If you don't want that don't set tolerant >= 2 */
+		/* do_exit takes an awful lot of locks and has as
+		   slight risk of deadlocking. If you don't want that
+		   don't set tolerant >= 2 */
 		if (tolerant < 3)
 			do_exit(SIGBUS);
 	}
-}
 
-static void mce_clear_all(void)
-{
-	int i;
-	for (i = 0; i < banks; i++)
-		wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0);
+ out:
+	/* Last thing done in the machine check exception to clear state. */
 	wrmsrl(MSR_IA32_MCG_STATUS, 0);
 }
 
@@ -268,22 +270,25 @@
 	int i;
 
 	rdmsrl(MSR_IA32_MCG_CAP, cap);
-	if (cap & MCG_CTL_P)
-		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
-
 	banks = cap & 0xff;
 	if (banks > NR_BANKS) { 
 		printk(KERN_INFO "MCE: warning: using only %d banks\n", banks);
 		banks = NR_BANKS; 
 	}
 
-	mce_clear_all(); 
+	/* Log the machine checks left over from the previous reset.
+	   This also clears all registers */
+	do_machine_check(NULL, -1);
+
+	set_in_cr4(X86_CR4_MCE);
+
+	if (cap & MCG_CTL_P)
+		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
+
 	for (i = 0; i < banks; i++) {
 		wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
 		wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
 	}	
-
-	set_in_cr4(X86_CR4_MCE);
 }
 
 /* Add per CPU specific workarounds here */
@@ -307,7 +312,9 @@
 
 	mce_cpu_quirks(c); 
 
-	if (test_and_set_bit(smp_processor_id(), &mce_cpus) || !mce_available(c))
+	if (mce_dont_init ||
+	    test_and_set_bit(smp_processor_id(), &mce_cpus) ||
+	    !mce_available(c))
 		return;
 
 	mce_init(NULL);
@@ -410,15 +417,16 @@
 
 static int __init mcheck_disable(char *str)
 {
-	mce_disabled = 1;
+	mce_dont_init = 1;
 	return 0;
 }
 
-/* mce=off disable machine check */
+/* mce=off disables machine check. Note you can reenable it later
+   using sysfs */
 static int __init mcheck_enable(char *str)
 {
 	if (!strcmp(str, "off"))
-		mce_disabled = 1;
+		mce_dont_init = 1;
 	else
 		printk("mce= argument %s ignored. Please use /sys", str); 
 	return 0;
@@ -434,7 +442,6 @@
 /* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */
 static int mce_resume(struct sys_device *dev)
 {
-	mce_clear_all();
 	on_each_cpu(mce_init, NULL, 1, 1);
 	return 0;
 }
@@ -492,7 +499,7 @@
 	if (!err)
 		err = sysdev_register(&device_mce);
 	if (!err) { 
-		/* could create per CPU objects, but is not worth it. */
+		/* could create per CPU objects, but it is not worth it. */
 		sysdev_create_file(&device_mce, &attr_bank0ctl); 
 		sysdev_create_file(&device_mce, &attr_bank1ctl); 
 		sysdev_create_file(&device_mce, &attr_bank2ctl); 
diff -Nru a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c
--- a/arch/x86_64/kernel/msr.c	2004-05-30 07:32:49 -07:00
+++ b/arch/x86_64/kernel/msr.c	2004-08-24 02:08:31 -07:00
@@ -46,234 +46,229 @@
 
 static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
 {
-  int err;
+	int err;
 
-  asm volatile(
-	       "1:	wrmsr\n"
-	       "2:\n"
-	       ".section .fixup,\"ax\"\n"
-	       "3:	movl %4,%0\n"
-	       "	jmp 2b\n"
-	       ".previous\n"
-	       ".section __ex_table,\"a\"\n"
-	       "	.align 8\n"
-	       "	.quad 1b,3b\n"
-	       ".previous"
-	       : "=&bDS" (err)
-	       : "a" (eax), "d" (edx), "c" (reg), "i" (-EIO), "0" (0));
+	asm volatile ("1:	wrmsr\n"
+		      "2:\n"
+		      ".section .fixup,\"ax\"\n"
+		      "3:	movl %4,%0\n"
+		      "	jmp 2b\n"
+		      ".previous\n"
+		      ".section __ex_table,\"a\"\n"
+		      "	.align 8\n" "	.quad 1b,3b\n" ".previous":"=&bDS" (err)
+		      :"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0));
 
-  return err;
+	return err;
 }
 
 static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
 {
-  int err;
+	int err;
 
-  asm volatile(
-	       "1:	rdmsr\n"
-	       "2:\n"
-	       ".section .fixup,\"ax\"\n"
-	       "3:	movl %4,%0\n"
-	       "	jmp 2b\n"
-	       ".previous\n"
-	       ".section __ex_table,\"a\"\n"
-	       "	.align 8\n"
-	       "	.quad 1b,3b\n"
-	       ".previous"
-	       : "=&bDS" (err), "=a" (*eax), "=d" (*edx)
-	       : "c" (reg), "i" (-EIO), "0" (0));
+	asm volatile ("1:	rdmsr\n"
+		      "2:\n"
+		      ".section .fixup,\"ax\"\n"
+		      "3:	movl %4,%0\n"
+		      "	jmp 2b\n"
+		      ".previous\n"
+		      ".section __ex_table,\"a\"\n"
+		      "	.align 8\n"
+		      "	.quad 1b,3b\n"
+		      ".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx)
+		      :"c"(reg), "i"(-EIO), "0"(0));
 
-  return err;
+	return err;
 }
 
 #ifdef CONFIG_SMP
 
 struct msr_command {
-  int cpu;
-  int err;
-  u32 reg;
-  u32 data[2];
+	int cpu;
+	int err;
+	u32 reg;
+	u32 data[2];
 };
 
 static void msr_smp_wrmsr(void *cmd_block)
 {
-  struct msr_command *cmd = (struct msr_command *) cmd_block;
-  
-  if ( cmd->cpu == smp_processor_id() )
-    cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
+	struct msr_command *cmd = (struct msr_command *)cmd_block;
+
+	if (cmd->cpu == smp_processor_id())
+		cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
 }
 
 static void msr_smp_rdmsr(void *cmd_block)
 {
-  struct msr_command *cmd = (struct msr_command *) cmd_block;
-  
-  if ( cmd->cpu == smp_processor_id() )
-    cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
+	struct msr_command *cmd = (struct msr_command *)cmd_block;
+
+	if (cmd->cpu == smp_processor_id())
+		cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
 }
 
 static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
 {
-  struct msr_command cmd;
-  int ret;
+	struct msr_command cmd;
+	int ret;
+
+	preempt_disable();
+	if (cpu == smp_processor_id()) {
+		ret = wrmsr_eio(reg, eax, edx);
+	} else {
+		cmd.cpu = cpu;
+		cmd.reg = reg;
+		cmd.data[0] = eax;
+		cmd.data[1] = edx;
 
-  preempt_disable();
-  if ( cpu == smp_processor_id() ) {
-    ret = wrmsr_eio(reg, eax, edx);
-  } else {
-    cmd.cpu = cpu;
-    cmd.reg = reg;
-    cmd.data[0] = eax;
-    cmd.data[1] = edx;
-    
-    smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
-    ret = cmd.err;
-  }
-  preempt_enable();
-  return ret;
+		smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
+		ret = cmd.err;
+	}
+	preempt_enable();
+	return ret;
 }
 
-static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
+static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx)
 {
-  struct msr_command cmd;
-  int ret;
+	struct msr_command cmd;
+	int ret;
+
+	preempt_disable();
+	if (cpu == smp_processor_id()) {
+		ret = rdmsr_eio(reg, eax, edx);
+	} else {
+		cmd.cpu = cpu;
+		cmd.reg = reg;
+
+		smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
 
-  preempt_disable();
-  if ( cpu == smp_processor_id() ) {
-    ret = rdmsr_eio(reg, eax, edx);
-  } else {
-    cmd.cpu = cpu;
-    cmd.reg = reg;
-
-    smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
-    
-    *eax = cmd.data[0];
-    *edx = cmd.data[1];
-
-    ret = cmd.err;
-  }
-  preempt_enable();
-  return ret;
+		*eax = cmd.data[0];
+		*edx = cmd.data[1];
+
+		ret = cmd.err;
+	}
+	preempt_enable();
+	return ret;
 }
 
-#else /* ! CONFIG_SMP */
+#else				/* ! CONFIG_SMP */
 
 static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
 {
-  return wrmsr_eio(reg, eax, edx);
+	return wrmsr_eio(reg, eax, edx);
 }
 
 static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
 {
-  return rdmsr_eio(reg, eax, edx);
+	return rdmsr_eio(reg, eax, edx);
 }
 
-#endif /* ! CONFIG_SMP */
+#endif				/* ! CONFIG_SMP */
 
 static loff_t msr_seek(struct file *file, loff_t offset, int orig)
 {
-  loff_t ret = -EINVAL;
-  lock_kernel();
-  switch (orig) {
-  case 0:
-    file->f_pos = offset;
-    ret = file->f_pos;
-    break;
-  case 1:
-    file->f_pos += offset;
-    ret = file->f_pos;
-  }
-  unlock_kernel();
-  return ret;
-}
-
-static ssize_t msr_read(struct file * file, char __user * buf,
-			size_t count, loff_t *ppos)
-{
-  char __user *tmp = buf;
-  u32 data[2];
-  size_t rv;
-  u32 reg = *ppos;
-  int cpu = iminor(file->f_dentry->d_inode);
-  int err;
-
-  if ( count % 8 )
-    return -EINVAL; /* Invalid chunk size */
-  
-  for ( rv = 0 ; count ; count -= 8 ) {
-    err = do_rdmsr(cpu, reg, &data[0], &data[1]);
-    if ( err )
-      return err;
-    if ( copy_to_user(tmp,&data,8) )
-      return -EFAULT;
-    tmp += 8;
-  }
+	loff_t ret = -EINVAL;
+
+	lock_kernel();
+	switch (orig) {
+	case 0:
+		file->f_pos = offset;
+		ret = file->f_pos;
+		break;
+	case 1:
+		file->f_pos += offset;
+		ret = file->f_pos;
+	}
+	unlock_kernel();
+	return ret;
+}
+
+static ssize_t msr_read(struct file *file, char __user * buf,
+			size_t count, loff_t * ppos)
+{
+	u32 __user *tmp = (u32 __user *) buf;
+	u32 data[2];
+	size_t rv;
+	u32 reg = *ppos;
+	int cpu = iminor(file->f_dentry->d_inode);
+	int err;
+
+	if (count % 8)
+		return -EINVAL;	/* Invalid chunk size */
+
+	for (rv = 0; count; count -= 8) {
+		err = do_rdmsr(cpu, reg, &data[0], &data[1]);
+		if (err)
+			return err;
+		if (copy_to_user(tmp, &data, 8))
+			return -EFAULT;
+		tmp += 2;
+	}
 
-  return tmp - buf;
+	return ((char __user *)tmp) - buf;
 }
 
-static ssize_t msr_write(struct file * file, const char __user * buf,
+static ssize_t msr_write(struct file *file, const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
-  const char __user *tmp = buf;
-  u32 data[2];
-  size_t rv;
-  u32 reg = *ppos;
-  int cpu = iminor(file->f_dentry->d_inode);
-  int err;
-
-  if ( count % 8 )
-    return -EINVAL; /* Invalid chunk size */
-  
-  for ( rv = 0 ; count ; count -= 8 ) {
-    if ( copy_from_user(&data,tmp,8) )
-      return -EFAULT;
-    err = do_wrmsr(cpu, reg, data[0], data[1]);
-    if ( err )
-      return err;
-    tmp += 8;
-  }
+	const u32 __user *tmp = (const u32 __user *)buf;
+	u32 data[2];
+	size_t rv;
+	u32 reg = *ppos;
+	int cpu = iminor(file->f_dentry->d_inode);
+	int err;
+
+	if (count % 8)
+		return -EINVAL;	/* Invalid chunk size */
+
+	for (rv = 0; count; count -= 8) {
+		if (copy_from_user(&data, tmp, 8))
+			return -EFAULT;
+		err = do_wrmsr(cpu, reg, data[0], data[1]);
+		if (err)
+			return err;
+		tmp += 2;
+	}
 
-  return tmp - buf;
+	return ((char __user *)tmp) - buf;
 }
 
 static int msr_open(struct inode *inode, struct file *file)
 {
-  int cpu = iminor(file->f_dentry->d_inode);
-  struct cpuinfo_x86 *c = &(cpu_data)[cpu];
-  
-  if (cpu >= NR_CPUS || !cpu_online(cpu))
-    return -ENXIO;		/* No such CPU */
-  if ( !cpu_has(c, X86_FEATURE_MSR) )
-    return -EIO;		/* MSR not supported */
-  
-  return 0;
+	unsigned int cpu = iminor(file->f_dentry->d_inode);
+	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
+
+	if (cpu >= NR_CPUS || !cpu_online(cpu))
+		return -ENXIO;	/* No such CPU */
+	if (!cpu_has(c, X86_FEATURE_MSR))
+		return -EIO;	/* MSR not supported */
+
+	return 0;
 }
 
 /*
  * File operations we support
  */
 static struct file_operations msr_fops = {
-  .owner =	THIS_MODULE,
-  .llseek =	msr_seek,
-  .read =	msr_read,
-  .write =	msr_write,
-  .open =	msr_open,
+	.owner = THIS_MODULE,
+	.llseek = msr_seek,
+	.read = msr_read,
+	.write = msr_write,
+	.open = msr_open,
 };
 
 int __init msr_init(void)
 {
-  if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
-    printk(KERN_ERR "msr: unable to get major %d for msr\n",
-	   MSR_MAJOR);
-    return -EBUSY;
-  }
-  
-  return 0;
+	if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
+		printk(KERN_ERR "msr: unable to get major %d for msr\n",
+		       MSR_MAJOR);
+		return -EBUSY;
+	}
+
+	return 0;
 }
 
 void __exit msr_exit(void)
 {
-  unregister_chrdev(MSR_MAJOR, "cpu/msr");
+	unregister_chrdev(MSR_MAJOR, "cpu/msr");
 }
 
 module_init(msr_init);
diff -Nru a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
--- a/arch/x86_64/kernel/pci-dma.c	2004-01-06 04:18:42 -08:00
+++ b/arch/x86_64/kernel/pci-dma.c	2004-08-24 02:08:31 -07:00
@@ -1,5 +1,5 @@
 /*
- * Dynamic DMA mapping support. Common code
+ * Dynamic DMA mapping support.
  */
 
 #include <linux/types.h>
@@ -24,38 +24,37 @@
  * Device ownership issues as mentioned above for pci_map_single are
  * the same here.
  */
-int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-			     int nents, int direction)
+int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
+	       int nents, int direction)
 {
 	int i;
 
-	BUG_ON(direction == PCI_DMA_NONE);
+	BUG_ON(direction == DMA_NONE);
  	for (i = 0; i < nents; i++ ) {
 		struct scatterlist *s = &sg[i];
 		BUG_ON(!s->page); 
-			s->dma_address = pci_map_page(hwdev, s->page, s->offset, 
-						      s->length, direction); 
+		s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
 		s->dma_length = s->length;
 	}
 	return nents;
 }
 
-EXPORT_SYMBOL(pci_map_sg);
+EXPORT_SYMBOL(dma_map_sg);
 
 /* Unmap a set of streaming mode DMA translations.
  * Again, cpu read rules concerning calls here are the same as for
  * pci_unmap_single() above.
  */
-void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, 
-				  int nents, int dir)
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+		  int nents, int dir)
 {
 	int i;
 	for (i = 0; i < nents; i++) { 
 		struct scatterlist *s = &sg[i];
 		BUG_ON(s->page == NULL); 
 		BUG_ON(s->dma_address == 0); 
-		pci_unmap_single(dev, s->dma_address, s->dma_length, dir); 
+		dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
 	} 
 }
 
-EXPORT_SYMBOL(pci_unmap_sg);
+EXPORT_SYMBOL(dma_unmap_sg);
diff -Nru a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
--- a/arch/x86_64/kernel/pci-gart.c	2004-07-27 17:23:25 -07:00
+++ b/arch/x86_64/kernel/pci-gart.c	2004-08-24 02:08:31 -07:00
@@ -31,12 +31,6 @@
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
 
-#ifdef CONFIG_PREEMPT
-#define preempt_atomic() in_atomic()
-#else
-#define preempt_atomic() 1
-#endif
-
 dma_addr_t bad_dma_address;
 
 unsigned long iommu_bus_base;	/* GART remapping area (physical) */
@@ -54,7 +48,7 @@
 int panic_on_overflow = 0;
 int force_iommu = 0;
 #endif
-int iommu_merge = 0; 
+int iommu_merge = 1;
 int iommu_sac_force = 0; 
 
 /* If this is disabled the IOMMU will use an optimized flushing strategy
@@ -64,6 +58,10 @@
    also seen with Qlogic at least). */
 int iommu_fullflush = 1;
 
+/* This tells the BIO block layer to assume merging. Default to off
+   because we cannot guarantee merging later. */
+int iommu_bio_merge = 0;
+
 #define MAX_NB 8
 
 /* Allocation bitmap for the remapping area */ 
@@ -104,8 +102,16 @@
 
 static unsigned long next_bit;  /* protected by iommu_bitmap_lock */
 static int need_flush; 		/* global flush state. set for each gart wrap */
-static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, 
-			       size_t size, int dir);
+static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem,
+			       size_t size, int dir, int do_panic);
+
+/* Dummy device used for NULL arguments (normally ISA). Better would
+   be probably a smaller DMA mask, but this is bug-to-bug compatible to i386. */
+static struct device fallback_dev = {
+	.bus_id = "fallback device",
+	.coherent_dma_mask = 0xffffffff,
+	.dma_mask = &fallback_dev.coherent_dma_mask,
+};
 
 static unsigned long alloc_iommu(int size) 
 { 	
@@ -146,25 +152,31 @@
 /* 
  * Use global flush state to avoid races with multiple flushers.
  */
-static void flush_gart(struct pci_dev *dev)
+static void flush_gart(struct device *dev)
 { 
 	unsigned long flags;
 	int flushed = 0;
-	int i;
+	int i, max;
 
 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
 	if (need_flush) { 
+		max = 0;
 		for (i = 0; i < MAX_NB; i++) {
-			u32 w;
 			if (!northbridges[i]) 
 				continue;
 			pci_write_config_dword(northbridges[i], 0x9c, 
 					       northbridge_flush_word[i] | 1); 
+			flushed++;
+			max = i;
+		}
+		for (i = 0; i <= max; i++) {
+			u32 w;
+			if (!northbridges[i])
+				continue;
 			/* Make sure the hardware actually executed the flush. */
 			do { 
 				pci_read_config_dword(northbridges[i], 0x9c, &w);
 			} while (w & 1);
-			flushed++;
 		} 
 		if (!flushed) 
 			printk("nothing to flush?\n");
@@ -173,31 +185,47 @@
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
 } 
 
+/* Allocate DMA memory on node near device */
+noinline
+static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
+{
+	struct page *page;
+	int node;
+	if (dev->bus == &pci_bus_type) {
+		cpumask_t mask;
+		mask = pcibus_to_cpumask(to_pci_dev(dev)->bus->number);
+		node = cpu_to_node(first_cpu(mask));
+	} else
+		node = numa_node_id();
+	page = alloc_pages_node(node, gfp, order);
+	return page ? page_address(page) : NULL;
+}
+
 /* 
- * Allocate memory for a consistent mapping.
+ * Allocate memory for a coherent mapping.
  */
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-			   dma_addr_t *dma_handle)
+void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		   unsigned gfp)
 {
 	void *memory;
-	int gfp = preempt_atomic() ? GFP_ATOMIC : GFP_KERNEL; 
 	unsigned long dma_mask = 0;
 	u64 bus;
 
-	if (hwdev) 
-		dma_mask = hwdev->dev.coherent_dma_mask;
+	if (!dev)
+		dev = &fallback_dev;
+	dma_mask = dev->coherent_dma_mask;
 	if (dma_mask == 0) 
 		dma_mask = 0xffffffff; 
 
 	/* Kludge to make it bug-to-bug compatible with i386. i386
-	   uses the normal dma_mask for alloc_consistent. */
-	if (hwdev)
-	dma_mask &= hwdev->dma_mask;
+	   uses the normal dma_mask for alloc_coherent. */
+	dma_mask &= *dev->dma_mask;
 
  again:
-	memory = (void *)__get_free_pages(gfp, get_order(size));
+	memory = dma_alloc_pages(dev, gfp, get_order(size));
 	if (memory == NULL)
-		return NULL; 
+		return NULL;
 
 	{
 		int high, mmu;
@@ -223,28 +251,29 @@
 		}
 	} 
 
-	*dma_handle = pci_map_area(hwdev, bus, size, PCI_DMA_BIDIRECTIONAL);
+	*dma_handle = dma_map_area(dev, bus, size, PCI_DMA_BIDIRECTIONAL, 0);
 	if (*dma_handle == bad_dma_address)
 		goto error; 
-	flush_gart(hwdev);	
+	flush_gart(dev);
 	return memory; 
 	
 error:
 	if (panic_on_overflow)
-		panic("pci_alloc_consistent: overflow %lu bytes\n", size); 
+		panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", size);
 free:
 	free_pages((unsigned long)memory, get_order(size)); 
+	/* XXX Could use the swiotlb pool here too */
 	return NULL; 
 }
 
 /* 
- * Unmap consistent memory.
+ * Unmap coherent memory.
  * The caller must ensure that the device has finished accessing the mapping.
  */
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t bus)
 {
-	pci_unmap_single(hwdev, bus, size, 0);
+	dma_unmap_single(dev, bus, size, 0);
 	free_pages((unsigned long)vaddr, get_order(size)); 		
 }
 
@@ -280,7 +309,7 @@
 #define CLEAR_LEAK(x)
 #endif
 
-static void iommu_full(struct pci_dev *dev, size_t size, int dir)
+static void iommu_full(struct device *dev, size_t size, int dir, int do_panic)
 {
 	/* 
 	 * Ran out of IOMMU space for this operation. This is very bad.
@@ -293,14 +322,14 @@
 	 */ 
 	
 	printk(KERN_ERR 
-  "PCI-DMA: Out of IOMMU space for %lu bytes at device %s[%s]\n",
-	       size, dev ? pci_pretty_name(dev) : "", dev ? dev->slot_name : "?");
+  "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n",
+	       size, dev->bus_id);
 
-	if (size > PAGE_SIZE*EMERGENCY_PAGES) {
+	if (size > PAGE_SIZE*EMERGENCY_PAGES && do_panic) {
 		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
-			panic("PCI-DMA: Memory will be corrupted\n");
+			panic("PCI-DMA: Memory would be corrupted\n");
 		if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) 
-			panic("PCI-DMA: Random memory will be DMAed\n"); 
+			panic("PCI-DMA: Random memory would be DMAed\n");
 	} 
 
 #ifdef CONFIG_IOMMU_LEAK
@@ -308,9 +337,9 @@
 #endif
 } 
 
-static inline int need_iommu(struct pci_dev *dev, unsigned long addr, size_t size)
+static inline int need_iommu(struct device *dev, unsigned long addr, size_t size)
 { 
-	u64 mask = dev ? dev->dma_mask : 0xffffffff;
+	u64 mask = *dev->dma_mask;
 	int high = addr + size >= mask;
 	int mmu = high;
 	if (force_iommu) 
@@ -323,9 +352,9 @@
 	return mmu; 
 }
 
-static inline int nonforced_iommu(struct pci_dev *dev, unsigned long addr, size_t size)
+static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
 { 
-	u64 mask = dev ? dev->dma_mask : 0xffffffff;
+	u64 mask = *dev->dma_mask;
 	int high = addr + size >= mask;
 	int mmu = high;
 	if (no_iommu) { 
@@ -339,8 +368,8 @@
 /* Map a single continuous physical area into the IOMMU.
  * Caller needs to check if the iommu is needed and flush.
  */
-static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, 
-				size_t size, int dir)
+static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem,
+				size_t size, int dir, int do_panic)
 { 
 	unsigned long npages = to_pages(phys_mem, size);
 	unsigned long iommu_page = alloc_iommu(npages);
@@ -349,8 +378,8 @@
 		if (!nonforced_iommu(dev, phys_mem, size))
 			return phys_mem; 
 		if (panic_on_overflow)
-			panic("pci_map_area overflow %lu bytes\n", size);
-		iommu_full(dev, size, dir);
+			panic("dma_map_area overflow %lu bytes\n", size);
+		iommu_full(dev, size, dir, do_panic);
 		return bad_dma_address;
 	}
 
@@ -363,44 +392,44 @@
 }
 
 /* Map a single area into the IOMMU */
-dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir)
-{ 
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, int dir)
+{
 	unsigned long phys_mem, bus;
 
-	BUG_ON(dir == PCI_DMA_NONE);
+	BUG_ON(dir == DMA_NONE);
 
-#ifdef CONFIG_SWIOTLB
 	if (swiotlb)
-		return swiotlb_map_single(&dev->dev,addr,size,dir);
-#endif
+		return swiotlb_map_single(dev,addr,size,dir);
+	if (!dev)
+		dev = &fallback_dev;
 
 	phys_mem = virt_to_phys(addr); 
 	if (!need_iommu(dev, phys_mem, size))
 		return phys_mem; 
 
-	bus = pci_map_area(dev, phys_mem, size, dir);
+	bus = dma_map_area(dev, phys_mem, size, dir, 1);
 	flush_gart(dev); 
 	return bus; 
 } 
 
-/* Fallback for pci_map_sg in case of overflow */ 
-static int pci_map_sg_nonforce(struct pci_dev *dev, struct scatterlist *sg,
+/* Fallback for dma_map_sg in case of overflow */
+static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
 			       int nents, int dir)
 {
 	int i;
 
 #ifdef CONFIG_IOMMU_DEBUG
-	printk(KERN_DEBUG "pci_map_sg overflow\n");
+	printk(KERN_DEBUG "dma_map_sg overflow\n");
 #endif
 
  	for (i = 0; i < nents; i++ ) {
 		struct scatterlist *s = &sg[i];
 		unsigned long addr = page_to_phys(s->page) + s->offset; 
 		if (nonforced_iommu(dev, addr, s->length)) { 
-			addr = pci_map_area(dev, addr, s->length, dir); 
+			addr = dma_map_area(dev, addr, s->length, dir, 0);
 			if (addr == bad_dma_address) { 
 				if (i > 0) 
-					pci_unmap_sg(dev, sg, i, dir); 
+					dma_unmap_sg(dev, sg, i, dir);
 				nents = 0; 
 				sg[0].dma_length = 0;
 				break;
@@ -414,7 +443,7 @@
 }
 
 /* Map multiple scatterlist entries continuous into the first. */
-static int __pci_map_cont(struct scatterlist *sg, int start, int stopat, 
+static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
 		      struct scatterlist *sout, unsigned long pages)
 {
 	unsigned long iommu_start = alloc_iommu(pages);
@@ -452,7 +481,7 @@
 	return 0;
 }
 
-static inline int pci_map_cont(struct scatterlist *sg, int start, int stopat, 
+static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat,
 		      struct scatterlist *sout,
 		      unsigned long pages, int need)
 {
@@ -462,14 +491,14 @@
 		sout->dma_length = sg[start].length; 
 		return 0;
 	} 
-	return __pci_map_cont(sg, start, stopat, sout, pages);
+	return __dma_map_cont(sg, start, stopat, sout, pages);
 }
 		
 /*
  * DMA map all entries in a scatterlist.
  * Merge chunks that have page aligned sizes into a continuous mapping. 
-		 */
-int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir)
+ */
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
 {
 	int i;
 	int out;
@@ -477,19 +506,14 @@
 	unsigned long pages = 0;
 	int need = 0, nextneed;
 
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_map_sg(&dev->dev,sg,nents,dir);
-#endif
-
-	BUG_ON(dir == PCI_DMA_NONE);
+	BUG_ON(dir == DMA_NONE);
 	if (nents == 0) 
 		return 0;
 
-#ifdef CONFIG_SWIOTLB
 	if (swiotlb)
-		return swiotlb_map_sg(&dev->dev,sg,nents,dir);
-#endif
+		return swiotlb_map_sg(dev,sg,nents,dir);
+	if (!dev)
+		dev = &fallback_dev;
 
 	out = 0;
 	start = 0;
@@ -508,19 +532,19 @@
 			   boundary and the new one doesn't have an offset. */
 			if (!iommu_merge || !nextneed || !need || s->offset ||
 			    (ps->offset + ps->length) % PAGE_SIZE) { 
-				if (pci_map_cont(sg, start, i, sg+out, pages, 
+				if (dma_map_cont(sg, start, i, sg+out, pages,
 						 need) < 0)
 					goto error;
 				out++;
 				pages = 0;
 				start = i;	
 			}
-	}
+		}
 
 		need = nextneed;
 		pages += to_pages(s->offset, s->length);
 	}
-	if (pci_map_cont(sg, start, i, sg+out, pages, need) < 0)
+	if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0)
 		goto error;
 	out++;
 	flush_gart(dev);
@@ -530,34 +554,32 @@
 
 error:
 	flush_gart(NULL);
-	pci_unmap_sg(dev, sg, nents, dir);
+	dma_unmap_sg(dev, sg, nents, dir);
 	/* When it was forced try again unforced */
 	if (force_iommu) 
-		return pci_map_sg_nonforce(dev, sg, nents, dir);
+		return dma_map_sg_nonforce(dev, sg, nents, dir);
 	if (panic_on_overflow)
-		panic("pci_map_sg: overflow on %lu pages\n", pages); 
-	iommu_full(dev, pages << PAGE_SHIFT, dir);
+		panic("dma_map_sg: overflow on %lu pages\n", pages);
+	iommu_full(dev, pages << PAGE_SHIFT, dir, 0);
 	for (i = 0; i < nents; i++)
 		sg[i].dma_address = bad_dma_address;
 	return 0;
 } 
 
 /*
- * Free a PCI mapping.
+ * Free a DMA mapping.
  */ 
-void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
 		      size_t size, int direction)
 {
 	unsigned long iommu_page; 
 	int npages;
 	int i;
 
-#ifdef CONFIG_SWIOTLB
 	if (swiotlb) {
-		swiotlb_unmap_single(&hwdev->dev,dma_addr,size,direction);
+		swiotlb_unmap_single(dev,dma_addr,size,direction);
 		return;
 	}
-#endif
 
 	if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || 
 	    dma_addr >= iommu_bus_base + iommu_size)
@@ -574,22 +596,25 @@
 /* 
  * Wrapper for pci_unmap_single working with scatterlists.
  */ 
-void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, 
-		  int dir)
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
 {
 	int i;
+	if (swiotlb) {
+		swiotlb_unmap_sg(dev,sg,nents,dir);
+		return;
+	}
 	for (i = 0; i < nents; i++) { 
 		struct scatterlist *s = &sg[i];
 		if (!s->dma_length || !s->length) 
 			break;
-		pci_unmap_single(dev, s->dma_address, s->dma_length, dir);
+		dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
 	}
 }
 
-int pci_dma_supported(struct pci_dev *dev, u64 mask)
+int dma_supported(struct device *dev, u64 mask)
 {
 	/* Copied from i386. Doesn't make much sense, because it will 
-	   only work for pci_alloc_consistent. 
+	   only work for pci_alloc_coherent.
 	   The caller just has to use GFP_DMA in this case. */
         if (mask < 0x00ffffff)
                 return 0;
@@ -605,22 +630,31 @@
 	   Assume all masks <= 40 bits are of this type. Normally this doesn't
 	   make any difference, but gives more gentle handling of IOMMU overflow. */
 	if (iommu_sac_force && (mask >= 0xffffffffffULL)) { 
-		printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->slot_name,mask);
+		printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask);
 		return 0; 
 	}
 
 	return 1;
 } 
 
-EXPORT_SYMBOL(pci_unmap_sg);
-EXPORT_SYMBOL(pci_map_sg);
-EXPORT_SYMBOL(pci_map_single);
-EXPORT_SYMBOL(pci_unmap_single);
-EXPORT_SYMBOL(pci_dma_supported);
+int dma_get_cache_alignment(void)
+{
+	return boot_cpu_data.x86_clflush_size;
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+EXPORT_SYMBOL(dma_map_sg);
+EXPORT_SYMBOL(dma_map_single);
+EXPORT_SYMBOL(dma_unmap_single);
+EXPORT_SYMBOL(dma_supported);
 EXPORT_SYMBOL(no_iommu);
 EXPORT_SYMBOL(force_iommu); 
 EXPORT_SYMBOL(bad_dma_address);
-EXPORT_SYMBOL(iommu_merge);
+EXPORT_SYMBOL(iommu_bio_merge);
+EXPORT_SYMBOL(iommu_sac_force);
+EXPORT_SYMBOL(dma_get_cache_alignment);
+EXPORT_SYMBOL(dma_alloc_coherent);
+EXPORT_SYMBOL(dma_free_coherent);
 
 static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)
 { 
@@ -747,7 +781,7 @@
 
 	if (swiotlb) { 
 		no_iommu = 1;
-		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for  IO (SWIOTLB)\n"); 
+		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
 		return -1; 
 	} 
 	
@@ -851,7 +885,7 @@
 fs_initcall(pci_iommu_init);
 
 /* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
-         [,forcesac][,fullflush][,nomerge]
+         [,forcesac][,fullflush][,nomerge][,biomerge]
    size  set size of iommu (in bytes) 
    noagp don't initialize the AGP driver and use full aperture.
    off   don't use the IOMMU
@@ -859,60 +893,73 @@
    memaper[=order] allocate an own aperture over RAM with size 32MB^order.  
    noforce don't force IOMMU usage. Default.
    force  Force IOMMU.
-   merge  Do SG merging. Implies force (experimental)  
+   merge  Do lazy merging. This may improve performance on some block devices.
+          Implies force (experimental)
+   biomerge Do merging at the BIO layer. This is more efficient than merge,
+            but should be only done with very big IOMMUs. Implies merge,force.
    nomerge Don't do SG merging.
    forcesac For SAC mode for masks <40bits  (experimental)
    fullflush Flush IOMMU on each allocation (default) 
    nofullflush Don't use IOMMU fullflush
    allowed  overwrite iommu off workarounds for specific chipsets.
    soft	 Use software bounce buffering (default for Intel machines)
+   noaperture Don't touch the aperture for AGP.
 */
-__init int iommu_setup(char *opt) 
+__init int iommu_setup(char *p)
 { 
     int arg;
-    char *p = opt;
-    
-    for (;;) { 
-	    if (!memcmp(p,"noagp", 5))
+
+    while (*p) {
+	    if (!strncmp(p,"noagp",5))
 		    no_agp = 1;
-	    if (!memcmp(p,"off", 3))
+	    if (!strncmp(p,"off",3))
 		    no_iommu = 1;
-	    if (!memcmp(p,"force", 5)) {
+	    if (!strncmp(p,"force",5)) {
 		    force_iommu = 1;
 		    iommu_aperture_allowed = 1;
 	    }
-	    if (!memcmp(p,"allowed",7))
+	    if (!strncmp(p,"allowed",7))
 		    iommu_aperture_allowed = 1;
-	    if (!memcmp(p,"noforce", 7)) { 
+	    if (!strncmp(p,"noforce",7)) {
 		    iommu_merge = 0;
 		    force_iommu = 0;
 	    }
-	    if (!memcmp(p, "memaper", 7)) { 
+	    if (!strncmp(p, "memaper", 7)) {
 		    fallback_aper_force = 1; 
 		    p += 7; 
-		    if (*p == '=' && get_option(&p, &arg))
-			    fallback_aper_order = arg;
+		    if (*p == '=') {
+			    ++p;
+			    if (get_option(&p, &arg))
+				    fallback_aper_order = arg;
+		    }
 	    } 
-	    if (!memcmp(p, "panic", 5))
+	    if (!strncmp(p, "biomerge",8)) {
+		    iommu_bio_merge = 4096;
+		    iommu_merge = 1;
+		    force_iommu = 1;
+	    }
+	    if (!strncmp(p, "panic",5))
 		    panic_on_overflow = 1;
-	    if (!memcmp(p, "nopanic", 7))
+	    if (!strncmp(p, "nopanic",7))
 		    panic_on_overflow = 0;	    
-	    if (!memcmp(p, "merge", 5)) { 
+	    if (!strncmp(p, "merge",5)) {
 		    iommu_merge = 1;
 		    force_iommu = 1; 
 	    }
-	    if (!memcmp(p, "nomerge", 7))
+	    if (!strncmp(p, "nomerge",7))
 		    iommu_merge = 0;
-	    if (!memcmp(p, "forcesac", 8))
+	    if (!strncmp(p, "forcesac",8))
 		    iommu_sac_force = 1;
-	    if (!memcmp(p, "fullflush", 9))
+	    if (!strncmp(p, "fullflush",8))
 		    iommu_fullflush = 1;
-	    if (!memcmp(p, "nofullflush", 11))
+	    if (!strncmp(p, "nofullflush",11))
 		    iommu_fullflush = 0;
-	    if (!memcmp(p, "soft", 4))
+	    if (!strncmp(p, "soft",4))
 		    swiotlb = 1;
+	    if (!strncmp(p, "noaperture",10))
+		    fix_aperture = 0;
 #ifdef CONFIG_IOMMU_LEAK
-	    if (!memcmp(p,"leak", 4)) { 
+	    if (!strncmp(p,"leak",4)) {
 		    leak_trace = 1;
 		    p += 4; 
 		    if (*p == '=') ++p;
@@ -922,10 +969,9 @@
 #endif
 	    if (isdigit(*p) && get_option(&p, &arg)) 
 		    iommu_size = arg;
-	    do {
-		    if (*p == ' ' || *p == 0) 
-			    return 0; 
-	    } while (*p++ != ','); 
+	    p += strcspn(p, ",");
+	    if (*p == ',')
+		    ++p;
     }
     return 1;
 } 
diff -Nru a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
--- a/arch/x86_64/kernel/pci-nommu.c	2004-05-09 05:37:57 -07:00
+++ b/arch/x86_64/kernel/pci-nommu.c	2004-08-24 02:08:31 -07:00
@@ -1,8 +1,11 @@
+/* Fallback functions when the main IOMMU code is not compiled in. This
+   code is roughly equivalent to i386. */
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <asm/proto.h>
+#include <asm/processor.h>
 
 int iommu_merge = 0;
 EXPORT_SYMBOL(iommu_merge);
@@ -10,57 +13,80 @@
 dma_addr_t bad_dma_address;
 EXPORT_SYMBOL(bad_dma_address);
 
+int iommu_bio_merge = 0;
+EXPORT_SYMBOL(iommu_bio_merge);
+
+int iommu_sac_force = 0;
+EXPORT_SYMBOL(iommu_sac_force);
+
 /* 
  * Dummy IO MMU functions
  */
 
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-			   dma_addr_t *dma_handle)
+void *dma_alloc_coherent(struct device *hwdev, size_t size,
+			 dma_addr_t *dma_handle, unsigned gfp)
 {
 	void *ret;
-	int gfp = GFP_ATOMIC;
-	
-	if (hwdev == NULL ||
-	    end_pfn > (hwdev->dma_mask>>PAGE_SHIFT) ||  /* XXX */
-	    (u32)hwdev->dma_mask < 0xffffffff)
-		gfp |= GFP_DMA;
-	ret = (void *)__get_free_pages(gfp, get_order(size));
+	u64 mask;
+	int order = get_order(size);
 
-	if (ret != NULL) {
-		memset(ret, 0, size);
+	if (hwdev)
+		mask = hwdev->coherent_dma_mask & *hwdev->dma_mask;
+	else
+		mask = 0xffffffff;
+	for (;;) {
+		ret = (void *)__get_free_pages(gfp, order);
+		if (ret == NULL)
+			return NULL;
 		*dma_handle = virt_to_bus(ret);
+		if ((*dma_handle & ~mask) == 0)
+			break;
+		free_pages((unsigned long)ret, order);
+		if (gfp & GFP_DMA)
+			return NULL;
+		gfp |= GFP_DMA;
 	}
+
+	memset(ret, 0, size);
 	return ret;
 }
+EXPORT_SYMBOL(dma_alloc_coherent);
 
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+void dma_free_coherent(struct device *hwdev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
 	free_pages((unsigned long)vaddr, get_order(size));
 }
+EXPORT_SYMBOL(dma_free_coherent);
 
-int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
+int dma_supported(struct device *hwdev, u64 mask)
 {
         /*
          * we fall back to GFP_DMA when the mask isn't all 1s,
          * so we can't guarantee allocations that must be
          * within a tighter range than GFP_DMA..
-		 * RED-PEN this won't work for pci_map_single. Caller has to
-		 * use GFP_DMA in the first place.
+	 * RED-PEN this won't work for pci_map_single. Caller has to
+	 * use GFP_DMA in the first place.
          */
         if (mask < 0x00ffffff)
                 return 0;
 
 	return 1;
 } 
+EXPORT_SYMBOL(dma_supported);
 
-EXPORT_SYMBOL(pci_dma_supported);
+int dma_get_cache_alignment(void)
+{
+	return boot_cpu_data.x86_clflush_size;
+}
+EXPORT_SYMBOL(dma_get_cache_alignment);
 
 static int __init check_ram(void) 
 { 
 	if (end_pfn >= 0xffffffff>>PAGE_SHIFT) { 
-		printk(KERN_ERR "WARNING more than 4GB of memory but no IOMMU.\n"
-		       KERN_ERR "WARNING 32bit PCI may malfunction.\n"); 
+		printk(
+		KERN_ERR "WARNING more than 4GB of memory but IOMMU not compiled in.\n"
+		KERN_ERR "WARNING 32bit PCI may malfunction.\n");
 	} 
 	return 0;
 } 
diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
--- a/arch/x86_64/kernel/process.c	2004-05-30 12:49:35 -07:00
+++ b/arch/x86_64/kernel/process.c	2004-08-24 02:08:44 -07:00
@@ -168,9 +168,7 @@
 	if (cpu_has(c, X86_FEATURE_MWAIT)) {
 		/*
 		 * Skip, if setup has overridden idle.
-		 * Also, take care of system with asymmetric CPUs.
-		 * Use, mwait_idle only if all cpus support it.
-		 * If not, we fallback to default_idle()
+		 * One CPU supports mwait => All CPUs supports mwait
 		 */
 		if (!pm_idle) {
 			if (!printed) {
@@ -179,10 +177,7 @@
 			}
 			pm_idle = mwait_idle;
 		}
-		return;
 	}
-	pm_idle = default_idle;
-	return;
 }
 
 static int __init idle_setup (char *str)
@@ -546,17 +541,16 @@
 	clear_thread_flag(TIF_IA32); 
 }
 
-asmlinkage long sys_fork(struct pt_regs regs)
+asmlinkage long sys_fork(struct pt_regs *regs)
 {
-	return do_fork(SIGCHLD, regs.rsp, &regs, 0, NULL, NULL);
+	return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL);
 }
 
-asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs regs)
+asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
 {
 	if (!newsp)
-		newsp = regs.rsp;
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, 
-		    parent_tid, child_tid);
+		newsp = regs->rsp;
+	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
 
 /*
@@ -569,9 +563,9 @@
  * do not have enough call-clobbered registers to hold all
  * the information you need.
  */
-asmlinkage long sys_vfork(struct pt_regs regs)
+asmlinkage long sys_vfork(struct pt_regs *regs)
 {
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, &regs, 0, 
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0,
 		    NULL, NULL);
 }
 
diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
--- a/arch/x86_64/kernel/ptrace.c	2004-08-23 01:14:58 -07:00
+++ b/arch/x86_64/kernel/ptrace.c	2004-08-24 02:08:31 -07:00
@@ -433,30 +433,32 @@
 		break;
 
 	case PTRACE_GETREGS: { /* Get all gp regs from the child. */
-	  	if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, FRAME_SIZE)) {
+	  	if (!access_ok(VERIFY_WRITE, (unsigned __user *)data,
+			       sizeof(struct user_regs_struct))) {
 			ret = -EIO;
 			break;
 		}
+		ret = 0;
 		for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) {
-			__put_user(getreg(child, ui),(unsigned long __user *) data);
+			ret |= __put_user(getreg(child, ui),(unsigned long __user *) data);
 			data += sizeof(long);
 		}
-		ret = 0;
 		break;
 	}
 
 	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
 		unsigned long tmp;
-	  	if (!access_ok(VERIFY_READ, (unsigned __user *)data, FRAME_SIZE)) {
+	  	if (!access_ok(VERIFY_READ, (unsigned __user *)data,
+			       sizeof(struct user_regs_struct))) {
 			ret = -EIO;
 			break;
 		}
+		ret = 0;
 		for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) {
-			__get_user(tmp, (unsigned long __user *) data);
+			ret |= __get_user(tmp, (unsigned long __user *) data);
 			putreg(child, ui, tmp);
 			data += sizeof(long);
 		}
-		ret = 0;
 		break;
 	}
 
diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
--- a/arch/x86_64/kernel/setup.c	2004-07-13 13:49:38 -07:00
+++ b/arch/x86_64/kernel/setup.c	2004-08-24 02:08:48 -07:00
@@ -79,8 +79,10 @@
 
 unsigned long saved_video_mode;
 
+#ifdef CONFIG_SWIOTLB
 int swiotlb;
 EXPORT_SYMBOL(swiotlb);
+#endif
 
 /*
  * Setup options
@@ -765,6 +767,7 @@
 	{ 0x43, LVL_2,      512 },
 	{ 0x44, LVL_2,      1024 },
 	{ 0x45, LVL_2,      2048 },
+	{ 0x60, LVL_1_DATA, 16 },
 	{ 0x66, LVL_1_DATA, 8 },
 	{ 0x67, LVL_1_DATA, 16 },
 	{ 0x68, LVL_1_DATA, 32 },
@@ -1059,8 +1062,8 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Intel-defined (#2) */
-		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2",
-		"est", NULL, "cid", NULL, NULL, "cmpxchg16b", NULL, NULL,
+		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est",
+		"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
--- a/arch/x86_64/kernel/setup64.c	2004-05-30 04:34:53 -07:00
+++ b/arch/x86_64/kernel/setup64.c	2004-08-24 02:08:31 -07:00
@@ -60,12 +60,12 @@
 */ 
 static int __init nonx_setup(char *str)
 {
-	if (!strncmp(str, "on",3)) { 
+	if (!strcmp(str, "on")) {
                 __supported_pte_mask |= _PAGE_NX; 
  		do_not_nx = 0; 
  		vm_data_default_flags &= ~VM_EXEC; 
  		vm_stack_flags &= ~VM_EXEC;  
-	} else if (!strncmp(str, "noforce",7) || !strncmp(str,"off",3)) { 
+	} else if (!strcmp(str, "noforce") || !strcmp(str, "off")) {
 		do_not_nx = (str[0] == 'o');
 		if (do_not_nx)
 			__supported_pte_mask &= ~_PAGE_NX; 
@@ -91,26 +91,28 @@
    compat    (default) Imply PROT_EXEC for PROT_READ
 
 */
- static int __init nonx32_setup(char *str)
+ static int __init nonx32_setup(char *s)
  {
-	char *s;
-	while ((s = strsep(&str, ",")) != NULL) { 
-		if (!strcmp(s, "all") || !strcmp(s,"on")) {
+	 while (*s) {
+		if (!strncmp(s, "all", 3) || !strncmp(s,"on",2)) {
 			vm_data_default_flags32 &= ~VM_EXEC; 
 			vm_stack_flags32 &= ~VM_EXEC;  
-		} else if (!strcmp(s, "off")) { 
+		} else if (!strncmp(s, "off",3)) {
 			vm_data_default_flags32 |= VM_EXEC; 
 			vm_stack_flags32 |= VM_EXEC;  
-		} else if (!strcmp(s, "stack")) { 
+		} else if (!strncmp(s, "stack", 5)) {
 			vm_data_default_flags32 |= VM_EXEC; 
 			vm_stack_flags32 &= ~VM_EXEC;  		
-		} else if (!strcmp(s, "force")) { 
+		} else if (!strncmp(s, "force",5)) {
 			vm_force_exec32 = 0; 
-		} else if (!strcmp(s, "compat")) { 
+		} else if (!strncmp(s, "compat",5)) {
 			vm_force_exec32 = PROT_EXEC;
 		} 
-	} 
- 	return 1;
+		s += strcspn(s, ",");
+		if (*s == ',')
+			++s;
+	 }
+	 return 1;
 } 
 
 __setup("noexec32=", nonx32_setup); 
diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
--- a/arch/x86_64/kernel/signal.c	2004-07-16 06:40:31 -07:00
+++ b/arch/x86_64/kernel/signal.c	2004-08-25 10:13:41 -07:00
@@ -40,7 +40,7 @@
             sigset_t *set, struct pt_regs * regs); 
 
 asmlinkage long
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs regs)
+sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
 {
 	sigset_t saveset, newset;
 
@@ -59,21 +59,22 @@
 	spin_unlock_irq(&current->sighand->siglock);
 #ifdef DEBUG_SIG
 	printk("rt_sigsuspend savset(%lx) newset(%lx) regs(%p) rip(%lx)\n",
-		saveset, newset, &regs, regs.rip);
+		saveset, newset, regs, regs->rip);
 #endif 
-	regs.rax = -EINTR;
+	regs->rax = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&regs, &saveset))
+		if (do_signal(regs, &saveset))
 			return -EINTR;
 	}
 }
 
 asmlinkage long
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs regs)
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+		struct pt_regs *regs)
 {
-	return do_sigaltstack(uss, uoss, regs.rsp);
+	return do_sigaltstack(uss, uoss, regs->rsp);
 }
 
 
@@ -134,13 +135,13 @@
 	return 1;
 }
 
-asmlinkage long sys_rt_sigreturn(struct pt_regs regs)
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	sigset_t set;
 	long eax;
 
-	frame = (struct rt_sigframe __user *)(regs.rsp - 8);
+	frame = (struct rt_sigframe __user *)(regs->rsp - 8);
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame))) { 
 		goto badframe;
 	} 
@@ -154,7 +155,7 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	
-	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &eax)) { 
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) {
 		goto badframe;
 	} 
 
@@ -162,13 +163,13 @@
 	printk("%d sigreturn rip:%lx rsp:%lx frame:%p rax:%lx\n",current->pid,regs.rip,regs.rsp,frame,eax);
 #endif
 
-	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs.rsp) == -EFAULT)
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->rsp) == -EFAULT)
 		goto badframe;
 
 	return eax;
 
 badframe:
-	signal_fault(&regs,frame,"sigreturn");
+	signal_fault(regs,frame,"sigreturn");
 	return 0;
 }	
 
@@ -287,7 +288,7 @@
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
 	} else {
-		printk("%s forgot to set SA_RESTORER for signal %d.\n", me->comm, sig); 
+		/* could use a vstub here */
 		goto give_sigsegv; 
 	}
 
@@ -328,9 +329,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	signal_fault(regs,frame,"signal deliver");
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -338,11 +337,9 @@
  */	
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+		sigset_t *oldset, struct pt_regs *regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 #ifdef DEBUG_SIG
 	printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig, 
 		regs->rip, regs->rsp, regs);
@@ -379,9 +376,6 @@
 #endif
 	setup_rt_frame(sig, ka, info, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -398,6 +392,7 @@
  */
 int do_signal(struct pt_regs *regs, sigset_t *oldset)
 {
+	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
@@ -419,7 +414,7 @@
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Reenable any watchpoints before delivering the
 		 * signal to user space. The processor register will
@@ -430,7 +425,7 @@
 			asm volatile("movq %0,%%db7"	: : "r" (current->thread.debugreg7));
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &info, &ka, oldset, regs);
 		return 1;
 	}
 
diff -Nru a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
--- a/arch/x86_64/kernel/smpboot.c	2004-07-28 12:24:29 -07:00
+++ b/arch/x86_64/kernel/smpboot.c	2004-08-24 02:08:12 -07:00
@@ -392,16 +392,6 @@
 extern volatile unsigned long init_rsp; 
 extern void (*initial_code)(void);
 
-static struct task_struct * __init fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/*
-	 * don't care about the eip and regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 #if APIC_DEBUG
 static inline void inquire_remote_apic(int apicid)
 {
@@ -575,19 +565,10 @@
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
 	 */
-	idle = fork_by_hand();
+	idle = fork_idle(cpu);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpu);
-	wake_up_forked_process(idle);	
 	x86_cpu_to_apicid[cpu] = apicid;
-
-	/*
-	 * We remove it from the pidhash and the runqueue
-	 * once we got the process:
-	 */
-	init_idle(idle,cpu);
-
-	unhash_process(idle);
 
 	cpu_pda[cpu].pcurrent = idle;
 
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c	2004-06-24 01:55:53 -07:00
+++ b/arch/x86_64/kernel/time.c	2004-08-26 23:30:31 -07:00
@@ -11,7 +11,6 @@
  *  Copyright (c) 2002  Vojtech Pavlik
  *  Copyright (c) 2003  Andi Kleen
  *  RTC support code taken from arch/i386/kernel/timers/time_hpet.c
- *
  */
 
 #include <linux/kernel.h>
@@ -42,6 +41,10 @@
 
 EXPORT_SYMBOL(jiffies_64);
 
+#ifdef CONFIG_CPU_FREQ
+static void cpufreq_delayed_get(void);
+#endif
+
 extern int using_apic_timer;
 
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -82,7 +85,7 @@
  * timer interrupt has happened already, but vxtime.trigger wasn't updated yet.
  * This is not a problem, because jiffies hasn't updated either. They are bound
  * together by xtime_lock.
-         */
+ */
 
 static inline unsigned int do_gettimeoffset_tsc(void)
 {
@@ -119,7 +122,7 @@
 		usec = xtime.tv_nsec / 1000;
 
 		/* i386 does some correction here to keep the clock 
-		   monotonus even when ntpd is fixing drift.
+		   monotonous even when ntpd is fixing drift.
 		   But they didn't work for me, there is a non monotonic
 		   clock anyways with ntp.
 		   I dropped all corrections now until a real solution can
@@ -214,7 +217,7 @@
  * overflow. This avoids messing with unknown time zones but requires your RTC
  * not to be off by more than 15 minutes. Since we're calling it only when
  * our clock is externally synchronized using NTP, this shouldn't be a problem.
-	 */
+ */
 
 	real_seconds = nowtime % 60;
 	real_minutes = nowtime / 60;
@@ -297,15 +300,15 @@
 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	static unsigned long rtc_update = 0;
-	unsigned long tsc, lost = 0;
-	int delay, offset = 0;
+	unsigned long tsc;
+	int delay, offset = 0, lost = 0;
 
 /*
  * Here we are in the timer irq handler. We have irqs locally disabled (so we
  * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
  * on the other CPU, so we need a lock. We also need to lock the vsyscall
  * variables, because both do_timer() and us change them -arca+vojtech
-	 */
+ */
 
 	write_seqlock(&xtime_lock);
 
@@ -354,12 +357,29 @@
 				(((long) offset << 32) / vxtime.tsc_quot) - 1;
 	}
 
-	if (lost) {
+	if (lost > 0) {
+		static long lost_count;
+
 		if (report_lost_ticks) {
-			printk(KERN_WARNING "time.c: Lost %ld timer "
+			printk(KERN_WARNING "time.c: Lost %d timer "
 			       "tick(s)! ", lost);
 			print_symbol("rip %s)\n", regs->rip);
 		}
+
+		if (lost_count == 100) {
+			printk(KERN_WARNING
+   "warning: many lost ticks.\n"
+   KERN_WARNING "Your time source seems to be instable or some driver is hogging interupts\n");
+			print_symbol("rip %s\n", regs->rip);
+			lost_count = 0;
+		} else
+			lost_count++;
+
+		if ((lost_count % 25) == 0) {
+#ifdef CONFIG_CPU_FREQ
+			cpufreq_delayed_get();
+#endif
+		}
 		jiffies += lost;
 	}
 
@@ -376,7 +396,7 @@
  */
 
 #ifndef CONFIG_X86_LOCAL_APIC
-	x86_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #else
 	if (!using_apic_timer)
 		smp_local_timer_interrupt(regs);
@@ -509,6 +529,34 @@
    Should fix up last_tsc too. Currently gettimeofday in the
    first tick after the change will be slightly wrong. */
 
+#include <linux/workqueue.h>
+
+static unsigned int cpufreq_delayed_issched = 0;
+static unsigned int cpufreq_init = 0;
+static struct work_struct cpufreq_delayed_get_work;
+
+static void handle_cpufreq_delayed_get(void *v)
+{
+	unsigned int cpu;
+	for_each_online_cpu(cpu) {
+		cpufreq_get(cpu);
+	}
+	cpufreq_delayed_issched = 0;
+}
+
+/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries
+ * to verify the CPU frequency the timing core thinks the CPU is running
+ * at is still correct.
+ */
+static void cpufreq_delayed_get(void)
+{
+	if (cpufreq_init && !cpufreq_delayed_issched) {
+		cpufreq_delayed_issched = 1;
+		printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n");
+		schedule_work(&cpufreq_delayed_get_work);
+	}
+}
+
 static unsigned int  ref_freq = 0;
 static unsigned long loops_per_jiffy_ref = 0;
 
@@ -518,14 +566,18 @@
 				 void *data)
 {
         struct cpufreq_freqs *freq = data;
-	unsigned long *lpj;
+	unsigned long *lpj, dummy;
 
+	lpj = &dummy;
+	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
 #ifdef CONFIG_SMP
 	lpj = &cpu_data[freq->cpu].loops_per_jiffy;
 #else
 	lpj = &boot_cpu_data.loops_per_jiffy;
 #endif
 
+
+
 	if (!ref_freq) {
 		ref_freq = freq->old;
 		loops_per_jiffy_ref = *lpj;
@@ -538,7 +590,8 @@
 		cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
 
 		cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
-		vxtime.tsc_quot = (1000L << 32) / cpu_khz;
+		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+			vxtime.tsc_quot = (1000L << 32) / cpu_khz;
 	}
 	
 	set_cyc2ns_scale(cpu_khz_ref / 1000);
@@ -549,6 +602,18 @@
 static struct notifier_block time_cpufreq_notifier_block = {
          .notifier_call  = time_cpufreq_notifier
 };
+
+static int __init cpufreq_tsc(void)
+{
+	INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
+	if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
+				       CPUFREQ_TRANSITION_NOTIFIER))
+		cpufreq_init = 1;
+	return 0;
+}
+
+core_initcall(cpufreq_tsc);
+
 #endif
 
 /*
@@ -725,8 +790,8 @@
 		cpu_khz = hpet_calibrate_tsc();
 		timename = "HPET";
 	} else {
-	pit_init();
-	cpu_khz = pit_calibrate_tsc();
+		pit_init();
+		cpu_khz = pit_calibrate_tsc();
 		timename = "PIT";
 	}
 
@@ -742,11 +807,6 @@
 	setup_irq(0, &irq0);
 
 	set_cyc2ns_scale(cpu_khz / 1000);
-
-#ifdef CONFIG_CPU_FREQ
-	cpufreq_register_notifier(&time_cpufreq_notifier_block, 
-				  CPUFREQ_TRANSITION_NOTIFIER);
-#endif
 }
 
 void __init time_init_smp(void)
@@ -1037,6 +1097,8 @@
 	return IRQ_HANDLED;
 }
 #endif
+
+
 
 static int __init nohpet_setup(char *s) 
 { 
diff -Nru a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
--- a/arch/x86_64/kernel/traps.c	2004-07-13 06:09:17 -07:00
+++ b/arch/x86_64/kernel/traps.c	2004-08-24 02:08:31 -07:00
@@ -352,7 +352,7 @@
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	printk("DEBUG_PAGEALLOC");
 #endif
-		printk("\n");
+	printk("\n");
 	notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
 	show_registers(regs);
 	/* Executive summary in case the oops scrolled away */
@@ -513,7 +513,7 @@
 		tsk->thread.error_code = error_code;
 		tsk->thread.trap_no = 13;
 		force_sig(SIGSEGV, tsk);
-	return;
+		return;
 	} 
 
 	/* kernel gp */
@@ -670,7 +670,6 @@
 	return regs;
 
 clear_TF_reenable:
-	printk("clear_tf_reenable\n");
 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
 
 clear_TF:
@@ -681,16 +680,43 @@
 	return regs;	
 }
 
+static int kernel_math_error(struct pt_regs *regs, char *str)
+{
+	const struct exception_table_entry *fixup;
+	fixup = search_exception_tables(regs->rip);
+	if (fixup) {
+		regs->rip = fixup->fixup;
+		return 1;
+	}
+	notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE);
+#if 0
+	/* This should be a die, but warn only for now */
+	die(str, regs, 0);
+#else
+	printk(KERN_DEBUG "%s: %s at ", current->comm, str);
+	printk_address(regs->rip);
+	printk("\n");
+#endif
+	return 0;
+}
+
 /*
  * Note that we play around with the 'TS' bit in an attempt to get
  * the correct behaviour even in the presence of the asynchronous
  * IRQ13 behaviour
  */
-void math_error(void __user *rip)
+asmlinkage void do_coprocessor_error(struct pt_regs *regs)
 {
+	void __user *rip = (void __user *)(regs->rip);
 	struct task_struct * task;
 	siginfo_t info;
 	unsigned short cwd, swd;
+
+	conditional_sti(regs);
+	if ((regs->cs & 3) == 0 &&
+	    kernel_math_error(regs, "kernel x87 math error"))
+		return;
+
 	/*
 	 * Save the info for the exception handler and clear the error.
 	 */
@@ -740,23 +766,23 @@
 	force_sig_info(SIGFPE, &info, task);
 }
 
-asmlinkage void do_coprocessor_error(struct pt_regs * regs)
-{
-	conditional_sti(regs);
-	math_error((void __user *)regs->rip);
-}
-
 asmlinkage void bad_intr(void)
 {
 	printk("bad interrupt"); 
 }
 
-static inline void simd_math_error(void __user *rip)
+asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
 {
+	void __user *rip = (void __user *)(regs->rip);
 	struct task_struct * task;
 	siginfo_t info;
 	unsigned short mxcsr;
 
+	conditional_sti(regs);
+	if ((regs->cs & 3) == 0 &&
+        	kernel_math_error(regs, "simd math error"))
+		return;
+
 	/*
 	 * Save the info for the exception handler and clear the error.
 	 */
@@ -797,12 +823,6 @@
 			break;
 	}
 	force_sig_info(SIGFPE, &info, task);
-}
-
-asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs)
-{
-	conditional_sti(regs);
-		simd_math_error((void __user *)regs->rip);
 }
 
 asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs)
diff -Nru a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
--- a/arch/x86_64/kernel/vmlinux.lds.S	2004-05-30 04:33:25 -07:00
+++ b/arch/x86_64/kernel/vmlinux.lds.S	2004-08-24 02:08:55 -07:00
@@ -91,9 +91,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
--- a/arch/x86_64/kernel/x8664_ksyms.c	2004-06-20 18:23:42 -07:00
+++ b/arch/x86_64/kernel/x8664_ksyms.c	2004-08-24 02:08:31 -07:00
@@ -108,11 +108,8 @@
 EXPORT_SYMBOL(pci_mem_start);
 #endif
 
-#ifdef CONFIG_X86_USE_3DNOW
-EXPORT_SYMBOL(_mmx_memcpy);
-EXPORT_SYMBOL(mmx_clear_page);
-EXPORT_SYMBOL(mmx_copy_page);
-#endif
+EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(clear_page);
 
 EXPORT_SYMBOL(cpu_pda);
 #ifdef CONFIG_SMP
@@ -182,10 +179,17 @@
 EXPORT_SYMBOL_NOVERS(__memcpy);
 EXPORT_SYMBOL_NOVERS(memcmp);
 
-/* syscall export needed for misdesigned sound drivers. */
-EXPORT_SYMBOL(sys_read);
-EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_open);
+#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
+/* prototypes are wrong, these are assembly with custom calling functions */
+extern void rwsem_down_read_failed_thunk(void);
+extern void rwsem_wake_thunk(void);
+extern void rwsem_downgrade_thunk(void);
+extern void rwsem_down_write_failed_thunk(void);
+EXPORT_SYMBOL(rwsem_down_read_failed_thunk);
+EXPORT_SYMBOL(rwsem_wake_thunk);
+EXPORT_SYMBOL(rwsem_downgrade_thunk);
+EXPORT_SYMBOL(rwsem_down_write_failed_thunk);
+#endif
 
 EXPORT_SYMBOL(empty_zero_page);
 
@@ -211,10 +215,9 @@
 extern unsigned long __supported_pte_mask;
 EXPORT_SYMBOL(__supported_pte_mask);
 
-EXPORT_SYMBOL(clear_page);
-
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL_GPL(flush_tlb_all);
 #endif
 
+EXPORT_SYMBOL(cpu_khz);
diff -Nru a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile
--- a/arch/x86_64/lib/Makefile	2004-05-17 14:12:13 -07:00
+++ b/arch/x86_64/lib/Makefile	2004-08-24 02:08:31 -07:00
@@ -8,7 +8,7 @@
 
 lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
 	usercopy.o getuser.o putuser.o  \
-	thunk.o clear_page.o copy_page.o bitstr.o
+	thunk.o clear_page.o copy_page.o bitstr.o bitops.o
 lib-y += memcpy.o memmove.o memset.o copy_user.o
 
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff -Nru a/arch/x86_64/lib/bitops.c b/arch/x86_64/lib/bitops.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/x86_64/lib/bitops.c	2004-08-24 11:20:01 -07:00
@@ -0,0 +1,140 @@
+#include <linux/module.h>
+#include <asm/bitops.h>
+
+#undef find_first_zero_bit
+#undef find_next_zero_bit
+#undef find_first_bit
+#undef find_next_bit
+
+/**
+ * find_first_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first zero bit, not the number of the byte
+ * containing a bit.
+ */
+inline long find_first_zero_bit(const unsigned long * addr, unsigned long size)
+{
+	long d0, d1, d2;
+	long res;
+
+	if (!size)
+		return 0;
+	asm volatile(
+		"  repe; scasq\n"
+		"  je 1f\n"
+		"  xorq -8(%%rdi),%%rax\n"
+		"  subq $8,%%rdi\n"
+		"  bsfq %%rax,%%rdx\n"
+		"1:  subq %[addr],%%rdi\n"
+		"  shlq $3,%%rdi\n"
+		"  addq %%rdi,%%rdx"
+		:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+		:"0" (0ULL), "1" ((size + 63) >> 6), "2" (addr), "3" (-1ULL),
+		 [addr] "r" (addr) : "memory");
+	return res;
+}
+
+/**
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+long find_next_zero_bit (const unsigned long * addr, long size, long offset)
+{
+	unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
+	unsigned long set = 0;
+	unsigned long res, bit = offset&63;
+
+	if (bit) {
+		/*
+		 * Look for zero in first word
+		 */
+		asm("bsfq %1,%0\n\t"
+		    "cmoveq %2,%0"
+		    : "=r" (set)
+		    : "r" (~(*p >> bit)), "r"(64L));
+		if (set < (64 - bit))
+			return set + offset;
+		set = 64 - bit;
+		p++;
+	}
+	/*
+	 * No zero yet, search remaining full words for a zero
+	 */
+	res = find_first_zero_bit ((const unsigned long *)p,
+				   size - 64 * (p - (unsigned long *) addr));
+	return (offset + set + res);
+}
+
+static inline long
+__find_first_bit(const unsigned long * addr, unsigned long size)
+{
+	long d0, d1;
+	long res;
+
+	asm volatile(
+		"   repe; scasq\n"
+		"   jz 1f\n"
+		"   subq $8,%%rdi\n"
+		"   bsfq (%%rdi),%%rax\n"
+		"1: subq %[addr],%%rdi\n"
+		"   shlq $3,%%rdi\n"
+		"   addq %%rdi,%%rax"
+		:"=a" (res), "=&c" (d0), "=&D" (d1)
+		:"0" (0ULL),
+		 "1" ((size + 63) >> 6), "2" (addr),
+		 [addr] "r" (addr) : "memory");
+	return res;
+}
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first set bit, not the number of the byte
+ * containing a bit.
+ */
+long find_first_bit(const unsigned long * addr, unsigned long size)
+{
+	return __find_first_bit(addr,size);
+}
+
+/**
+ * find_next_bit - find the first set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+long find_next_bit(const unsigned long * addr, long size, long offset)
+{
+	const unsigned long * p = addr + (offset >> 6);
+	unsigned long set = 0, bit = offset & 63, res;
+
+	if (bit) {
+		/*
+		 * Look for nonzero in the first 64 bits:
+		 */
+		asm("bsfq %1,%0\n\t"
+		    "cmoveq %2,%0\n\t"
+		    : "=r" (set)
+		    : "r" (*p >> bit), "r" (64L));
+		if (set < (64 - bit))
+			return set + offset;
+		set = 64 - bit;
+		p++;
+	}
+	/*
+	 * No set bit yet, search remaining full words for a bit
+	 */
+	res = __find_first_bit (p, size - 64 * (p - addr));
+	return (offset + set + res);
+}
+
+EXPORT_SYMBOL(find_next_bit);
+EXPORT_SYMBOL(find_first_bit);
+EXPORT_SYMBOL(find_first_zero_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
diff -Nru a/arch/x86_64/lib/bitstr.c b/arch/x86_64/lib/bitstr.c
--- a/arch/x86_64/lib/bitstr.c	2002-10-11 16:52:38 -07:00
+++ b/arch/x86_64/lib/bitstr.c	2004-08-24 02:08:31 -07:00
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <asm/bitops.h>
 
 /* Find string of zero bits in a bitmap */ 
@@ -23,3 +24,5 @@
 	}
 	return n;
 }
+
+EXPORT_SYMBOL(find_next_zero_string);
diff -Nru a/arch/x86_64/lib/memmove.c b/arch/x86_64/lib/memmove.c
--- a/arch/x86_64/lib/memmove.c	2002-06-11 17:40:31 -07:00
+++ b/arch/x86_64/lib/memmove.c	2004-08-24 02:08:31 -07:00
@@ -10,18 +10,10 @@
 	if (dest < src) { 
 		__inline_memcpy(dest,src,count);
 	} else {
-		/* Could be more clever and move longs */
-		unsigned long d0, d1, d2;
-		__asm__ __volatile__(
-			"std\n\t"
-			"rep\n\t"
-			"movsb\n\t"
-			"cld"
-			: "=&c" (d0), "=&S" (d1), "=&D" (d2)
-			:"0" (count),
-			"1" (count-1+(const char *)src),
-			"2" (count-1+(char *)dest)
-			:"memory");
+		char *p = (char *) dest + count;
+		char *s = (char *) src + count;
+		while (count--)
+			*--p = *--s;
 	}
 	return dest;
 } 
diff -Nru a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
--- a/arch/x86_64/mm/fault.c	2004-07-13 05:59:29 -07:00
+++ b/arch/x86_64/mm/fault.c	2004-08-24 02:08:31 -07:00
@@ -58,16 +58,17 @@
 /* Sometimes the CPU reports invalid exceptions on prefetch.
    Check that here and ignore.
    Opcode checker based on code by Richard Brunner */
-static int is_prefetch(struct pt_regs *regs, unsigned long addr)
+static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
+				unsigned long error_code)
 { 
 	unsigned char *instr = (unsigned char *)(regs->rip);
 	int scan_more = 1;
 	int prefetch = 0; 
 	unsigned char *max_instr = instr + 15;
 
-	/* Avoid recursive faults for this common case */
-	if (regs->rip == addr)
-		return 0; 
+	/* If it was a exec fault ignore */
+	if (error_code & (1<<4))
+		return 0;
 	
 	/* Code segments in LDT could have a non zero base. Don't check
 	   when that's possible */
@@ -218,6 +219,18 @@
 		(tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
 }
 
+static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
+				 unsigned long error_code)
+{
+	oops_begin();
+	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
+	       current->comm, address);
+	dump_pagetable(address);
+	__die("Bad pagetable", regs, error_code);
+	oops_end();
+	do_exit(SIGKILL);
+}
+
 int page_fault_trace; 
 int exception_trace = 1;
 
@@ -268,11 +281,32 @@
 	mm = tsk->mm;
 	info.si_code = SEGV_MAPERR;
 
-	/* 5 => page not present and from supervisor mode */
-	if (unlikely(!(error_code & 5) &&
-		     ((address >= VMALLOC_START && address <= VMALLOC_END) ||
-		      (address >= MODULES_VADDR && address <= MODULES_END))))
-		goto vmalloc_fault;
+
+	/*
+	 * We fault-in kernel-space virtual memory on-demand. The
+	 * 'reference' page table is init_mm.pgd.
+	 *
+	 * NOTE! We MUST NOT take any locks for this case. We may
+	 * be in an interrupt or a critical region, and should
+	 * only copy the information from the master page table,
+	 * nothing more.
+	 *
+	 * This verifies that the fault happens in kernel space
+	 * (error_code & 4) == 0, and that the fault was not a
+	 * protection error (error_code & 1) == 0.
+	 */
+	if (unlikely(address >= TASK_SIZE)) {
+		if (!(error_code & 5))
+			goto vmalloc_fault;
+		/*
+		 * Don't take the mm semaphore here. If we fixup a prefetch
+		 * fault we could otherwise deadlock.
+		 */
+		goto bad_area_nosemaphore;
+	}
+
+	if (unlikely(error_code & (1 << 3)))
+		goto page_table_corruption;
 
 	/*
 	 * If we're in an interrupt or have no user
@@ -351,18 +385,18 @@
 bad_area_nosemaphore:
 
 #ifdef CONFIG_IA32_EMULATION
-		/* 32bit vsyscall. map on demand. */
-		if (test_thread_flag(TIF_IA32) && 
+	/* 32bit vsyscall. map on demand. */
+	if (test_thread_flag(TIF_IA32) &&
 	    address >= 0xffffe000 && address < 0xffffe000 + PAGE_SIZE) { 
-			if (map_syscall32(mm, address) < 0) 
-				goto out_of_memory2;
-			return;
-		} 			
+		if (map_syscall32(mm, address) < 0)
+			goto out_of_memory2;
+		return;
+	}
 #endif
 
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & 4) {
-		if (is_prefetch(regs, address))
+		if (is_prefetch(regs, address, error_code))
 			return;
 
 		/* Work around K8 erratum #100 K8 in compat mode
@@ -376,7 +410,7 @@
 			return;
 
 		if (exception_trace && unhandled_signal(tsk, SIGSEGV)) {
-		printk(KERN_INFO 
+			printk(KERN_INFO
 		       "%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n",
 					tsk->comm, tsk->pid, address, regs->rip,
 					regs->rsp, error_code);
@@ -407,7 +441,7 @@
 	 * Hall of shame of CPU/BIOS bugs.
 	 */
 
- 	if (is_prefetch(regs, address))
+ 	if (is_prefetch(regs, address, error_code))
  		return;
 
 	if (is_errata93(regs, address))
@@ -481,10 +515,8 @@
 		 * is really there and when yes flush the local TLB. 
 		 */
 		pgd = pgd_offset_k(address);
-		if (pgd != current_pgd_offset_k(address)) 
-			BUG(); 
 		if (!pgd_present(*pgd))
-				goto bad_area_nosemaphore;
+			goto bad_area_nosemaphore;
 		pmd = pmd_offset(pgd, address);
 		if (!pmd_present(*pmd))
 			goto bad_area_nosemaphore;
@@ -495,4 +527,7 @@
 		__flush_tlb_all();		
 		return;
 	}
+
+page_table_corruption:
+	pgtable_bad(address, regs, error_code);
 }
diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
--- a/arch/x86_64/mm/init.c	2004-06-24 01:55:57 -07:00
+++ b/arch/x86_64/mm/init.c	2004-08-24 02:08:31 -07:00
@@ -41,6 +41,10 @@
 #define Dprintk(x...)
 #endif
 
+#ifdef CONFIG_GART_IOMMU
+extern int swiotlb;
+#endif
+
 extern char _stext[];
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -396,6 +400,8 @@
 	return 0;
 }
 
+extern int swiotlb_force;
+
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
 			 kcore_vsyscall;
 
@@ -405,7 +411,10 @@
 	int tmp;
 
 #ifdef CONFIG_SWIOTLB
-	if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT)
+	if (swiotlb_force)
+		swiotlb = 1;
+	if (!iommu_aperture &&
+	    (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu))
 	       swiotlb = 1;
 	if (swiotlb)
 		swiotlb_init();	
@@ -596,7 +605,16 @@
 
 struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
 {
-	return test_tsk_thread_flag(tsk, TIF_IA32) ? &gate32_vma : &gate_vma;
+#ifdef CONFIG_IA32_EMULATION
+	if (test_tsk_thread_flag(tsk, TIF_IA32)) {
+		/* lookup code assumes the pages are present. set them up
+		   now */
+		if (map_syscall32(tsk->mm, 0xfffe000) < 0)
+			return NULL;
+		return &gate32_vma;
+	}
+#endif
+	return &gate_vma;
 }
 
 int in_gate_area(struct task_struct *task, unsigned long addr)
diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
--- a/arch/x86_64/mm/numa.c	2004-06-17 23:53:45 -07:00
+++ b/arch/x86_64/mm/numa.c	2004-08-24 02:08:33 -07:00
@@ -135,7 +135,7 @@
 		zones[ZONE_NORMAL] = end_pfn - start_pfn; 
 	} 
     
-	free_area_init_node(nodeid, NODE_DATA(nodeid), NULL, zones, 
+	free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
 			    start_pfn, NULL); 
 } 
 
diff -Nru a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile
--- a/arch/x86_64/pci/Makefile	2004-03-16 11:09:27 -08:00
+++ b/arch/x86_64/pci/Makefile	2004-08-24 02:08:31 -07:00
@@ -3,7 +3,7 @@
 #
 # Reuse the i386 PCI subsystem
 #
-CFLAGS += -I arch/i386/pci
+CFLAGS += -Iarch/i386/pci
 
 obj-y		:= i386.o
 obj-$(CONFIG_PCI_DIRECT)+= direct.o
@@ -12,6 +12,8 @@
 obj-y			+= legacy.o irq.o common.o
 # mmconfig has a 64bit special
 obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
+
+obj-$(CONFIG_NUMA)	+= k8-bus.o
 
 direct-y += ../../i386/pci/direct.o
 acpi-y   += ../../i386/pci/acpi.o
diff -Nru a/arch/x86_64/pci/Makefile-BUS b/arch/x86_64/pci/Makefile-BUS
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/x86_64/pci/Makefile-BUS	2004-08-24 11:20:02 -07:00
@@ -0,0 +1,22 @@
+#
+# Makefile for X86_64 specific PCI routines
+#
+# Reuse the i386 PCI subsystem
+#
+CFLAGS += -I arch/i386/pci
+
+obj-y		:= i386.o
+obj-$(CONFIG_PCI_DIRECT)+= direct.o
+obj-y		+= fixup.o
+obj-$(CONFIG_ACPI_PCI)	+= acpi.o
+obj-y			+= legacy.o irq.o common.o
+# mmconfig has a 64bit special
+obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
+
+direct-y += ../../i386/pci/direct.o
+acpi-y   += ../../i386/pci/acpi.o
+legacy-y += ../../i386/pci/legacy.o
+irq-y    += ../../i386/pci/irq.o
+common-y += ../../i386/pci/common.o
+fixup-y  += ../../i386/pci/fixup.o
+i386-y  += ../../i386/pci/i386.o
diff -Nru a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/x86_64/pci/k8-bus.c	2004-08-24 11:20:02 -07:00
@@ -0,0 +1,74 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mpspec.h>
+#include <linux/cpumask.h>
+
+/*
+ * This discovers the pcibus <-> node mapping on AMD K8.
+ *
+ * RED-PEN need to call this again on PCI hotplug
+ * RED-PEN empty cpus get reported wrong
+ */
+
+#define NODE_ID_REGISTER 0x60
+#define NODE_ID(dword) (dword & 0x07)
+#define LDT_BUS_NUMBER_REGISTER_0 0x94
+#define LDT_BUS_NUMBER_REGISTER_1 0xB4
+#define LDT_BUS_NUMBER_REGISTER_2 0xD4
+#define NR_LDT_BUS_NUMBER_REGISTERS 3
+#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
+#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
+#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
+
+/**
+ * fill_mp_bus_to_cpumask()
+ * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
+ * Registers found in the K8 northbridge
+ */
+__init static int
+fill_mp_bus_to_cpumask(void)
+{
+	struct pci_dev *nb_dev = NULL;
+	int i, j;
+	u32 ldtbus, nid;
+	static int lbnr[3] = {
+		LDT_BUS_NUMBER_REGISTER_0,
+		LDT_BUS_NUMBER_REGISTER_1,
+		LDT_BUS_NUMBER_REGISTER_2
+	};
+
+	while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+			PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
+		pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
+
+		for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
+			pci_read_config_dword(nb_dev, lbnr[i], &ldtbus);
+			/*
+			 * if there are no busses hanging off of the current
+			 * ldt link then both the secondary and subordinate
+			 * bus number fields are set to 0.
+			 */
+			if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0
+				&& SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) {
+				for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
+				     j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
+				     j++)
+					pci_bus_to_cpumask[j] =
+						node_to_cpumask(NODE_ID(nid));
+			}
+		}
+	}
+
+	/* quick sanity check */
+	for (i = 0; i < 256; i++) {
+		if (cpus_empty(pci_bus_to_cpumask[i])) {
+			printk(KERN_ERR
+			       "k8-bus.c: bus %i has empty cpu mask\n", i);
+			pci_bus_to_cpumask[i] = CPU_MASK_ALL;
+		}
+	}
+
+	return 0;
+}
+
+fs_initcall(fill_mp_bus_to_cpumask);
diff -Nru a/crypto/Kconfig b/crypto/Kconfig
--- a/crypto/Kconfig	2004-08-10 18:22:49 -07:00
+++ b/crypto/Kconfig	2004-08-24 11:26:41 -07:00
@@ -67,6 +67,21 @@
 	  This code also includes SHA-384, a 384 bit hash with 192 bits
 	  of security against collision attacks.
 
+config CRYPTO_WHIRLPOOL
+	tristate "Whirlpool digest algorithm"
+	depends on CRYPTO
+	help
+	  Whirlpool hash algorithm.
+
+	  Whirlpool is part of the NESSIE cryptographic primtives.
+	  Whirlpool works on messages shorter than 2^256 bits and
+	  produces a 512 bit hash.
+
+	  Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard
+
+	  See also:
+	  http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html
+
 config CRYPTO_DES
 	tristate "DES and Triple DES EDE cipher algorithms"
 	depends on CRYPTO
diff -Nru a/crypto/Makefile b/crypto/Makefile
--- a/crypto/Makefile	2004-08-09 16:43:25 -07:00
+++ b/crypto/Makefile	2004-08-24 11:26:41 -07:00
@@ -14,6 +14,7 @@
 obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
 obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
 obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
+obj-$(CONFIG_CRYPTO_WHIRLPOOL) += whirlpool.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c	2004-08-09 16:43:25 -07:00
+++ b/crypto/tcrypt.c	2004-08-26 23:41:48 -07:00
@@ -24,6 +24,7 @@
 #include <linux/string.h>
 #include <linux/crypto.h>
 #include <linux/highmem.h>
+#include <linux/moduleparam.h>
 #include "tcrypt.h"
 
 /*
@@ -61,7 +62,8 @@
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", NULL
+	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", 
+	"whirlpool", NULL
 };
 
 static void
@@ -680,6 +682,7 @@
 
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
+		test_hash("whirlpool", whirlpool_tv_template, WHIRLPOOL_TEST_VECTORS);
 		test_deflate();
 		test_crc32c();
 #ifdef CONFIG_CRYPTO_HMAC
@@ -791,6 +794,11 @@
 		test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS);
 		break;
 
+	case 22:
+		test_hash("whirlpool", whirlpool_tv_template, WHIRLPOOL_TEST_VECTORS);
+		break;
+
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
@@ -846,7 +854,7 @@
 module_init(init);
 module_exit(fini);
 
-MODULE_PARM(mode, "i");
+module_param(mode, int, 0);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Quick & dirty crypto testing module");
diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h
--- a/crypto/tcrypt.h	2004-08-10 18:25:40 -07:00
+++ b/crypto/tcrypt.h	2004-08-24 11:26:41 -07:00
@@ -301,6 +301,110 @@
 	},
 };
 
+
+/*
+ * WHIRLPOOL test vectors from Whirlpool package 
+ * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE
+ * submission
+ */
+#define WHIRLPOOL_TEST_VECTORS	8
+
+struct hash_testvec whirlpool_tv_template[] = {
+	{ 
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+			    0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+			    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+			    0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+			    0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB,
+			    0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
+			    0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37,
+			    0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 },
+
+
+	}, {
+		.plaintext = "a",
+		.psize	= 1,
+		.digest	= { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+			    0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+			    0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+			    0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42,
+			    0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6,
+			    0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59,
+			    0x1A, 0x92, 0x20, 0x0D, 0x56, 0x01, 0x95, 0xE5,
+			    0x3B, 0x47, 0x85, 0x84, 0xFD, 0xAE, 0x23, 0x1A },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+			    0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+			    0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+			    0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C,
+			    0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27,
+			    0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6,
+			    0xC7, 0x97, 0xFC, 0x9D, 0x95, 0xD8, 0xB5, 0x82,
+			    0xD2, 0x25, 0x29, 0x20, 0x76, 0xD4, 0xEE, 0xF5 },
+	}, {
+		.plaintext = "message digest",
+		.psize	= 14,
+		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, 
+			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, 
+			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, 
+			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, 
+			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, 
+			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6, 
+			    0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33, 
+			    0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+		.psize	= 26,
+		.digest	= { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+			    0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+			    0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+			    0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B,
+			    0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A,
+			    0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6,
+			    0xF6, 0x8F, 0x67, 0x3E, 0x72, 0x07, 0x86, 0x5D,
+			    0x5D, 0x98, 0x19, 0xA3, 0xDB, 0xA4, 0xEB, 0x3B },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+			     "abcdefghijklmnopqrstuvwxyz0123456789",
+		.psize	= 62,
+		.digest	= { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+			    0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+			    0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+			    0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E,
+			    0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F,
+			    0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6,
+			    0x55, 0x17, 0xCC, 0x87, 0x9D, 0x7B, 0x96, 0x21,
+			    0x42, 0xC6, 0x5F, 0x5A, 0x7A, 0xF0, 0x14, 0x67 },
+	}, {
+		.plaintext = "1234567890123456789012345678901234567890"
+			     "1234567890123456789012345678901234567890",
+		.psize	= 80,
+		.digest	= { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+			    0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+			    0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+			    0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29,
+			    0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5,
+			    0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A,
+			    0x2C, 0x60, 0x48, 0x1E, 0x88, 0xC5, 0xA2, 0x0B,
+			    0x2C, 0x2A, 0x80, 0xCF, 0x3A, 0x9A, 0x08, 0x3B },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+		.psize	= 32,
+		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, 
+			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
+			    0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B,
+			    0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56,
+			    0x93, 0x9B, 0xAA, 0xA0, 0xAD, 0xFF, 0x9A, 0xE6,
+			    0x74, 0x5B, 0x7B, 0x18, 0x1C, 0x3B, 0xE3, 0xFD },
+	},
+};
+
 #ifdef CONFIG_CRYPTO_HMAC
 /*
  * HMAC-MD5 test vectors from RFC2202
diff -Nru a/crypto/whirlpool.c b/crypto/whirlpool.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/crypto/whirlpool.c	2004-08-24 11:26:34 -07:00
@@ -0,0 +1,1131 @@
+/*
+ * Cryptographic API.
+ *
+ * Whirlpool hashing Algorithm
+ *
+ * The Whirlpool algorithm was developed by Paulo S. L. M. Barreto and
+ * Vincent Rijmen.  It has been selected as one of cryptographic
+ * primitives by the NESSIE project http://www.cryptonessie.org/
+ *
+ * The original authors have disclaimed all copyright interest in this
+ * code and thus put it in the public domain. The subsequent authors
+ * have put this under the GNU General Public License.
+ *
+ * By Aaron Grothe ajgrothe@yahoo.com, August 23, 2004
+ *
+ * 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 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define WHIRLPOOL_DIGEST_SIZE 64
+#define WHIRLPOOL_BLOCK_SIZE  64
+#define WHIRLPOOL_LENGTHBYTES 32
+
+#define WHIRLPOOL_ROUNDS 10
+
+struct whirlpool_ctx {
+	u8  bitLength[WHIRLPOOL_LENGTHBYTES];
+	u8  buffer[WHIRLPOOL_BLOCK_SIZE];
+	int bufferBits;
+	int bufferPos;
+	u64 hash[WHIRLPOOL_DIGEST_SIZE/8];
+};
+
+/*
+ * Though Whirlpool is endianness-neutral, the encryption tables are listed
+ * in BIG-ENDIAN format, which is adopted throughout this implementation
+ * (but little-endian notation would be equally suitable if consistently
+ * employed).
+ */
+
+static const u64 C0[256] = {
+	0x18186018c07830d8ULL, 0x23238c2305af4626ULL, 0xc6c63fc67ef991b8ULL,
+	0xe8e887e8136fcdfbULL, 0x878726874ca113cbULL, 0xb8b8dab8a9626d11ULL,
+	0x0101040108050209ULL, 0x4f4f214f426e9e0dULL, 0x3636d836adee6c9bULL,
+	0xa6a6a2a6590451ffULL, 0xd2d26fd2debdb90cULL, 0xf5f5f3f5fb06f70eULL,
+	0x7979f979ef80f296ULL, 0x6f6fa16f5fcede30ULL, 0x91917e91fcef3f6dULL,
+	0x52525552aa07a4f8ULL, 0x60609d6027fdc047ULL, 0xbcbccabc89766535ULL,
+	0x9b9b569baccd2b37ULL, 0x8e8e028e048c018aULL, 0xa3a3b6a371155bd2ULL,
+	0x0c0c300c603c186cULL, 0x7b7bf17bff8af684ULL, 0x3535d435b5e16a80ULL,
+	0x1d1d741de8693af5ULL, 0xe0e0a7e05347ddb3ULL, 0xd7d77bd7f6acb321ULL,
+	0xc2c22fc25eed999cULL, 0x2e2eb82e6d965c43ULL, 0x4b4b314b627a9629ULL,
+	0xfefedffea321e15dULL, 0x575741578216aed5ULL, 0x15155415a8412abdULL,
+	0x7777c1779fb6eee8ULL, 0x3737dc37a5eb6e92ULL, 0xe5e5b3e57b56d79eULL,
+	0x9f9f469f8cd92313ULL, 0xf0f0e7f0d317fd23ULL, 0x4a4a354a6a7f9420ULL,
+	0xdada4fda9e95a944ULL, 0x58587d58fa25b0a2ULL, 0xc9c903c906ca8fcfULL,
+	0x2929a429558d527cULL, 0x0a0a280a5022145aULL, 0xb1b1feb1e14f7f50ULL,
+	0xa0a0baa0691a5dc9ULL, 0x6b6bb16b7fdad614ULL, 0x85852e855cab17d9ULL,
+	0xbdbdcebd8173673cULL, 0x5d5d695dd234ba8fULL, 0x1010401080502090ULL,
+	0xf4f4f7f4f303f507ULL, 0xcbcb0bcb16c08bddULL, 0x3e3ef83eedc67cd3ULL,
+	0x0505140528110a2dULL, 0x676781671fe6ce78ULL, 0xe4e4b7e47353d597ULL,
+	0x27279c2725bb4e02ULL, 0x4141194132588273ULL, 0x8b8b168b2c9d0ba7ULL,
+	0xa7a7a6a7510153f6ULL, 0x7d7de97dcf94fab2ULL, 0x95956e95dcfb3749ULL,
+	0xd8d847d88e9fad56ULL, 0xfbfbcbfb8b30eb70ULL, 0xeeee9fee2371c1cdULL,
+	0x7c7ced7cc791f8bbULL, 0x6666856617e3cc71ULL, 0xdddd53dda68ea77bULL,
+	0x17175c17b84b2eafULL, 0x4747014702468e45ULL, 0x9e9e429e84dc211aULL,
+	0xcaca0fca1ec589d4ULL, 0x2d2db42d75995a58ULL, 0xbfbfc6bf9179632eULL,
+	0x07071c07381b0e3fULL, 0xadad8ead012347acULL, 0x5a5a755aea2fb4b0ULL,
+	0x838336836cb51befULL, 0x3333cc3385ff66b6ULL, 0x636391633ff2c65cULL,
+	0x02020802100a0412ULL, 0xaaaa92aa39384993ULL, 0x7171d971afa8e2deULL,
+	0xc8c807c80ecf8dc6ULL, 0x19196419c87d32d1ULL, 0x494939497270923bULL,
+	0xd9d943d9869aaf5fULL, 0xf2f2eff2c31df931ULL, 0xe3e3abe34b48dba8ULL,
+	0x5b5b715be22ab6b9ULL, 0x88881a8834920dbcULL, 0x9a9a529aa4c8293eULL,
+	0x262698262dbe4c0bULL, 0x3232c8328dfa64bfULL, 0xb0b0fab0e94a7d59ULL,
+	0xe9e983e91b6acff2ULL, 0x0f0f3c0f78331e77ULL, 0xd5d573d5e6a6b733ULL,
+	0x80803a8074ba1df4ULL, 0xbebec2be997c6127ULL, 0xcdcd13cd26de87ebULL,
+	0x3434d034bde46889ULL, 0x48483d487a759032ULL, 0xffffdbffab24e354ULL,
+	0x7a7af57af78ff48dULL, 0x90907a90f4ea3d64ULL, 0x5f5f615fc23ebe9dULL,
+	0x202080201da0403dULL, 0x6868bd6867d5d00fULL, 0x1a1a681ad07234caULL,
+	0xaeae82ae192c41b7ULL, 0xb4b4eab4c95e757dULL, 0x54544d549a19a8ceULL,
+	0x93937693ece53b7fULL, 0x222288220daa442fULL, 0x64648d6407e9c863ULL,
+	0xf1f1e3f1db12ff2aULL, 0x7373d173bfa2e6ccULL, 0x12124812905a2482ULL,
+	0x40401d403a5d807aULL, 0x0808200840281048ULL, 0xc3c32bc356e89b95ULL,
+	0xecec97ec337bc5dfULL, 0xdbdb4bdb9690ab4dULL, 0xa1a1bea1611f5fc0ULL,
+	0x8d8d0e8d1c830791ULL, 0x3d3df43df5c97ac8ULL, 0x97976697ccf1335bULL,
+	0x0000000000000000ULL, 0xcfcf1bcf36d483f9ULL, 0x2b2bac2b4587566eULL,
+	0x7676c57697b3ece1ULL, 0x8282328264b019e6ULL, 0xd6d67fd6fea9b128ULL,
+	0x1b1b6c1bd87736c3ULL, 0xb5b5eeb5c15b7774ULL, 0xafaf86af112943beULL,
+	0x6a6ab56a77dfd41dULL, 0x50505d50ba0da0eaULL, 0x45450945124c8a57ULL,
+	0xf3f3ebf3cb18fb38ULL, 0x3030c0309df060adULL, 0xefef9bef2b74c3c4ULL,
+	0x3f3ffc3fe5c37edaULL, 0x55554955921caac7ULL, 0xa2a2b2a2791059dbULL,
+	0xeaea8fea0365c9e9ULL, 0x656589650fecca6aULL, 0xbabad2bab9686903ULL,
+	0x2f2fbc2f65935e4aULL, 0xc0c027c04ee79d8eULL, 0xdede5fdebe81a160ULL,
+	0x1c1c701ce06c38fcULL, 0xfdfdd3fdbb2ee746ULL, 0x4d4d294d52649a1fULL,
+	0x92927292e4e03976ULL, 0x7575c9758fbceafaULL, 0x06061806301e0c36ULL,
+	0x8a8a128a249809aeULL, 0xb2b2f2b2f940794bULL, 0xe6e6bfe66359d185ULL,
+	0x0e0e380e70361c7eULL, 0x1f1f7c1ff8633ee7ULL, 0x6262956237f7c455ULL,
+	0xd4d477d4eea3b53aULL, 0xa8a89aa829324d81ULL, 0x96966296c4f43152ULL,
+	0xf9f9c3f99b3aef62ULL, 0xc5c533c566f697a3ULL, 0x2525942535b14a10ULL,
+	0x59597959f220b2abULL, 0x84842a8454ae15d0ULL, 0x7272d572b7a7e4c5ULL,
+	0x3939e439d5dd72ecULL, 0x4c4c2d4c5a619816ULL, 0x5e5e655eca3bbc94ULL,
+	0x7878fd78e785f09fULL, 0x3838e038ddd870e5ULL, 0x8c8c0a8c14860598ULL,
+	0xd1d163d1c6b2bf17ULL, 0xa5a5aea5410b57e4ULL, 0xe2e2afe2434dd9a1ULL,
+	0x616199612ff8c24eULL, 0xb3b3f6b3f1457b42ULL, 0x2121842115a54234ULL,
+	0x9c9c4a9c94d62508ULL, 0x1e1e781ef0663ceeULL, 0x4343114322528661ULL,
+	0xc7c73bc776fc93b1ULL, 0xfcfcd7fcb32be54fULL, 0x0404100420140824ULL,
+	0x51515951b208a2e3ULL, 0x99995e99bcc72f25ULL, 0x6d6da96d4fc4da22ULL,
+	0x0d0d340d68391a65ULL, 0xfafacffa8335e979ULL, 0xdfdf5bdfb684a369ULL,
+	0x7e7ee57ed79bfca9ULL, 0x242490243db44819ULL, 0x3b3bec3bc5d776feULL,
+	0xabab96ab313d4b9aULL, 0xcece1fce3ed181f0ULL, 0x1111441188552299ULL,
+	0x8f8f068f0c890383ULL, 0x4e4e254e4a6b9c04ULL, 0xb7b7e6b7d1517366ULL,
+	0xebeb8beb0b60cbe0ULL, 0x3c3cf03cfdcc78c1ULL, 0x81813e817cbf1ffdULL,
+	0x94946a94d4fe3540ULL, 0xf7f7fbf7eb0cf31cULL, 0xb9b9deb9a1676f18ULL,
+	0x13134c13985f268bULL, 0x2c2cb02c7d9c5851ULL, 0xd3d36bd3d6b8bb05ULL,
+	0xe7e7bbe76b5cd38cULL, 0x6e6ea56e57cbdc39ULL, 0xc4c437c46ef395aaULL,
+	0x03030c03180f061bULL, 0x565645568a13acdcULL, 0x44440d441a49885eULL,
+	0x7f7fe17fdf9efea0ULL, 0xa9a99ea921374f88ULL, 0x2a2aa82a4d825467ULL,
+	0xbbbbd6bbb16d6b0aULL, 0xc1c123c146e29f87ULL, 0x53535153a202a6f1ULL,
+	0xdcdc57dcae8ba572ULL, 0x0b0b2c0b58271653ULL, 0x9d9d4e9d9cd32701ULL,
+	0x6c6cad6c47c1d82bULL, 0x3131c43195f562a4ULL, 0x7474cd7487b9e8f3ULL,
+	0xf6f6fff6e309f115ULL, 0x464605460a438c4cULL, 0xacac8aac092645a5ULL,
+	0x89891e893c970fb5ULL, 0x14145014a04428b4ULL, 0xe1e1a3e15b42dfbaULL,
+	0x16165816b04e2ca6ULL, 0x3a3ae83acdd274f7ULL, 0x6969b9696fd0d206ULL,
+	0x09092409482d1241ULL, 0x7070dd70a7ade0d7ULL, 0xb6b6e2b6d954716fULL,
+	0xd0d067d0ceb7bd1eULL, 0xeded93ed3b7ec7d6ULL, 0xcccc17cc2edb85e2ULL,
+	0x424215422a578468ULL, 0x98985a98b4c22d2cULL, 0xa4a4aaa4490e55edULL,
+	0x2828a0285d885075ULL, 0x5c5c6d5cda31b886ULL, 0xf8f8c7f8933fed6bULL,
+	0x8686228644a411c2ULL,
+};
+
+static const u64 C1[256] = {
+	0xd818186018c07830ULL, 0x2623238c2305af46ULL, 0xb8c6c63fc67ef991ULL,
+	0xfbe8e887e8136fcdULL, 0xcb878726874ca113ULL, 0x11b8b8dab8a9626dULL,
+	0x0901010401080502ULL, 0x0d4f4f214f426e9eULL, 0x9b3636d836adee6cULL,
+	0xffa6a6a2a6590451ULL, 0x0cd2d26fd2debdb9ULL, 0x0ef5f5f3f5fb06f7ULL,
+	0x967979f979ef80f2ULL, 0x306f6fa16f5fcedeULL, 0x6d91917e91fcef3fULL,
+	0xf852525552aa07a4ULL, 0x4760609d6027fdc0ULL, 0x35bcbccabc897665ULL,
+	0x379b9b569baccd2bULL, 0x8a8e8e028e048c01ULL, 0xd2a3a3b6a371155bULL,
+	0x6c0c0c300c603c18ULL, 0x847b7bf17bff8af6ULL, 0x803535d435b5e16aULL,
+	0xf51d1d741de8693aULL, 0xb3e0e0a7e05347ddULL, 0x21d7d77bd7f6acb3ULL,
+	0x9cc2c22fc25eed99ULL, 0x432e2eb82e6d965cULL, 0x294b4b314b627a96ULL,
+	0x5dfefedffea321e1ULL, 0xd5575741578216aeULL, 0xbd15155415a8412aULL,
+	0xe87777c1779fb6eeULL, 0x923737dc37a5eb6eULL, 0x9ee5e5b3e57b56d7ULL,
+	0x139f9f469f8cd923ULL, 0x23f0f0e7f0d317fdULL, 0x204a4a354a6a7f94ULL,
+	0x44dada4fda9e95a9ULL, 0xa258587d58fa25b0ULL, 0xcfc9c903c906ca8fULL,
+	0x7c2929a429558d52ULL, 0x5a0a0a280a502214ULL, 0x50b1b1feb1e14f7fULL,
+	0xc9a0a0baa0691a5dULL, 0x146b6bb16b7fdad6ULL, 0xd985852e855cab17ULL,
+	0x3cbdbdcebd817367ULL, 0x8f5d5d695dd234baULL, 0x9010104010805020ULL,
+	0x07f4f4f7f4f303f5ULL, 0xddcbcb0bcb16c08bULL, 0xd33e3ef83eedc67cULL,
+	0x2d0505140528110aULL, 0x78676781671fe6ceULL, 0x97e4e4b7e47353d5ULL,
+	0x0227279c2725bb4eULL, 0x7341411941325882ULL, 0xa78b8b168b2c9d0bULL,
+	0xf6a7a7a6a7510153ULL, 0xb27d7de97dcf94faULL, 0x4995956e95dcfb37ULL,
+	0x56d8d847d88e9fadULL, 0x70fbfbcbfb8b30ebULL, 0xcdeeee9fee2371c1ULL,
+	0xbb7c7ced7cc791f8ULL, 0x716666856617e3ccULL, 0x7bdddd53dda68ea7ULL,
+	0xaf17175c17b84b2eULL, 0x454747014702468eULL, 0x1a9e9e429e84dc21ULL,
+	0xd4caca0fca1ec589ULL, 0x582d2db42d75995aULL, 0x2ebfbfc6bf917963ULL,
+	0x3f07071c07381b0eULL, 0xacadad8ead012347ULL, 0xb05a5a755aea2fb4ULL,
+	0xef838336836cb51bULL, 0xb63333cc3385ff66ULL, 0x5c636391633ff2c6ULL,
+	0x1202020802100a04ULL, 0x93aaaa92aa393849ULL, 0xde7171d971afa8e2ULL,
+	0xc6c8c807c80ecf8dULL, 0xd119196419c87d32ULL, 0x3b49493949727092ULL,
+	0x5fd9d943d9869aafULL, 0x31f2f2eff2c31df9ULL, 0xa8e3e3abe34b48dbULL,
+	0xb95b5b715be22ab6ULL, 0xbc88881a8834920dULL, 0x3e9a9a529aa4c829ULL,
+	0x0b262698262dbe4cULL, 0xbf3232c8328dfa64ULL, 0x59b0b0fab0e94a7dULL,
+	0xf2e9e983e91b6acfULL, 0x770f0f3c0f78331eULL, 0x33d5d573d5e6a6b7ULL,
+	0xf480803a8074ba1dULL, 0x27bebec2be997c61ULL, 0xebcdcd13cd26de87ULL,
+	0x893434d034bde468ULL, 0x3248483d487a7590ULL, 0x54ffffdbffab24e3ULL,
+	0x8d7a7af57af78ff4ULL, 0x6490907a90f4ea3dULL, 0x9d5f5f615fc23ebeULL,
+	0x3d202080201da040ULL, 0x0f6868bd6867d5d0ULL, 0xca1a1a681ad07234ULL,
+	0xb7aeae82ae192c41ULL, 0x7db4b4eab4c95e75ULL, 0xce54544d549a19a8ULL,
+	0x7f93937693ece53bULL, 0x2f222288220daa44ULL, 0x6364648d6407e9c8ULL,
+	0x2af1f1e3f1db12ffULL, 0xcc7373d173bfa2e6ULL, 0x8212124812905a24ULL,
+	0x7a40401d403a5d80ULL, 0x4808082008402810ULL, 0x95c3c32bc356e89bULL,
+	0xdfecec97ec337bc5ULL, 0x4ddbdb4bdb9690abULL, 0xc0a1a1bea1611f5fULL,
+	0x918d8d0e8d1c8307ULL, 0xc83d3df43df5c97aULL, 0x5b97976697ccf133ULL,
+	0x0000000000000000ULL, 0xf9cfcf1bcf36d483ULL, 0x6e2b2bac2b458756ULL,
+	0xe17676c57697b3ecULL, 0xe68282328264b019ULL, 0x28d6d67fd6fea9b1ULL,
+	0xc31b1b6c1bd87736ULL, 0x74b5b5eeb5c15b77ULL, 0xbeafaf86af112943ULL,
+	0x1d6a6ab56a77dfd4ULL, 0xea50505d50ba0da0ULL, 0x5745450945124c8aULL,
+	0x38f3f3ebf3cb18fbULL, 0xad3030c0309df060ULL, 0xc4efef9bef2b74c3ULL,
+	0xda3f3ffc3fe5c37eULL, 0xc755554955921caaULL, 0xdba2a2b2a2791059ULL,
+	0xe9eaea8fea0365c9ULL, 0x6a656589650feccaULL, 0x03babad2bab96869ULL,
+	0x4a2f2fbc2f65935eULL, 0x8ec0c027c04ee79dULL, 0x60dede5fdebe81a1ULL,
+	0xfc1c1c701ce06c38ULL, 0x46fdfdd3fdbb2ee7ULL, 0x1f4d4d294d52649aULL,
+	0x7692927292e4e039ULL, 0xfa7575c9758fbceaULL, 0x3606061806301e0cULL,
+	0xae8a8a128a249809ULL, 0x4bb2b2f2b2f94079ULL, 0x85e6e6bfe66359d1ULL,
+	0x7e0e0e380e70361cULL, 0xe71f1f7c1ff8633eULL, 0x556262956237f7c4ULL,
+	0x3ad4d477d4eea3b5ULL, 0x81a8a89aa829324dULL, 0x5296966296c4f431ULL,
+	0x62f9f9c3f99b3aefULL, 0xa3c5c533c566f697ULL, 0x102525942535b14aULL,
+	0xab59597959f220b2ULL, 0xd084842a8454ae15ULL, 0xc57272d572b7a7e4ULL,
+	0xec3939e439d5dd72ULL, 0x164c4c2d4c5a6198ULL, 0x945e5e655eca3bbcULL,
+	0x9f7878fd78e785f0ULL, 0xe53838e038ddd870ULL, 0x988c8c0a8c148605ULL,
+	0x17d1d163d1c6b2bfULL, 0xe4a5a5aea5410b57ULL, 0xa1e2e2afe2434dd9ULL,
+	0x4e616199612ff8c2ULL, 0x42b3b3f6b3f1457bULL, 0x342121842115a542ULL,
+	0x089c9c4a9c94d625ULL, 0xee1e1e781ef0663cULL, 0x6143431143225286ULL,
+	0xb1c7c73bc776fc93ULL, 0x4ffcfcd7fcb32be5ULL, 0x2404041004201408ULL,
+	0xe351515951b208a2ULL, 0x2599995e99bcc72fULL, 0x226d6da96d4fc4daULL,
+	0x650d0d340d68391aULL, 0x79fafacffa8335e9ULL, 0x69dfdf5bdfb684a3ULL,
+	0xa97e7ee57ed79bfcULL, 0x19242490243db448ULL, 0xfe3b3bec3bc5d776ULL,
+	0x9aabab96ab313d4bULL, 0xf0cece1fce3ed181ULL, 0x9911114411885522ULL,
+	0x838f8f068f0c8903ULL, 0x044e4e254e4a6b9cULL, 0x66b7b7e6b7d15173ULL,
+	0xe0ebeb8beb0b60cbULL, 0xc13c3cf03cfdcc78ULL, 0xfd81813e817cbf1fULL,
+	0x4094946a94d4fe35ULL, 0x1cf7f7fbf7eb0cf3ULL, 0x18b9b9deb9a1676fULL,
+	0x8b13134c13985f26ULL, 0x512c2cb02c7d9c58ULL, 0x05d3d36bd3d6b8bbULL,
+	0x8ce7e7bbe76b5cd3ULL, 0x396e6ea56e57cbdcULL, 0xaac4c437c46ef395ULL,
+	0x1b03030c03180f06ULL, 0xdc565645568a13acULL, 0x5e44440d441a4988ULL,
+	0xa07f7fe17fdf9efeULL, 0x88a9a99ea921374fULL, 0x672a2aa82a4d8254ULL,
+	0x0abbbbd6bbb16d6bULL, 0x87c1c123c146e29fULL, 0xf153535153a202a6ULL,
+	0x72dcdc57dcae8ba5ULL, 0x530b0b2c0b582716ULL, 0x019d9d4e9d9cd327ULL,
+	0x2b6c6cad6c47c1d8ULL, 0xa43131c43195f562ULL, 0xf37474cd7487b9e8ULL,
+	0x15f6f6fff6e309f1ULL, 0x4c464605460a438cULL, 0xa5acac8aac092645ULL,
+	0xb589891e893c970fULL, 0xb414145014a04428ULL, 0xbae1e1a3e15b42dfULL,
+	0xa616165816b04e2cULL, 0xf73a3ae83acdd274ULL, 0x066969b9696fd0d2ULL,
+	0x4109092409482d12ULL, 0xd77070dd70a7ade0ULL, 0x6fb6b6e2b6d95471ULL,
+	0x1ed0d067d0ceb7bdULL, 0xd6eded93ed3b7ec7ULL, 0xe2cccc17cc2edb85ULL,
+	0x68424215422a5784ULL, 0x2c98985a98b4c22dULL, 0xeda4a4aaa4490e55ULL,
+	0x752828a0285d8850ULL, 0x865c5c6d5cda31b8ULL, 0x6bf8f8c7f8933fedULL,
+	0xc28686228644a411ULL,
+};
+
+static const u64 C2[256] = {
+	0x30d818186018c078ULL, 0x462623238c2305afULL, 0x91b8c6c63fc67ef9ULL,
+	0xcdfbe8e887e8136fULL, 0x13cb878726874ca1ULL, 0x6d11b8b8dab8a962ULL,
+	0x0209010104010805ULL, 0x9e0d4f4f214f426eULL, 0x6c9b3636d836adeeULL,
+	0x51ffa6a6a2a65904ULL, 0xb90cd2d26fd2debdULL, 0xf70ef5f5f3f5fb06ULL,
+	0xf2967979f979ef80ULL, 0xde306f6fa16f5fceULL, 0x3f6d91917e91fcefULL,
+	0xa4f852525552aa07ULL, 0xc04760609d6027fdULL, 0x6535bcbccabc8976ULL,
+	0x2b379b9b569baccdULL, 0x018a8e8e028e048cULL, 0x5bd2a3a3b6a37115ULL,
+	0x186c0c0c300c603cULL, 0xf6847b7bf17bff8aULL, 0x6a803535d435b5e1ULL,
+	0x3af51d1d741de869ULL, 0xddb3e0e0a7e05347ULL, 0xb321d7d77bd7f6acULL,
+	0x999cc2c22fc25eedULL, 0x5c432e2eb82e6d96ULL, 0x96294b4b314b627aULL,
+	0xe15dfefedffea321ULL, 0xaed5575741578216ULL, 0x2abd15155415a841ULL,
+	0xeee87777c1779fb6ULL, 0x6e923737dc37a5ebULL, 0xd79ee5e5b3e57b56ULL,
+	0x23139f9f469f8cd9ULL, 0xfd23f0f0e7f0d317ULL, 0x94204a4a354a6a7fULL,
+	0xa944dada4fda9e95ULL, 0xb0a258587d58fa25ULL, 0x8fcfc9c903c906caULL,
+	0x527c2929a429558dULL, 0x145a0a0a280a5022ULL, 0x7f50b1b1feb1e14fULL,
+	0x5dc9a0a0baa0691aULL, 0xd6146b6bb16b7fdaULL, 0x17d985852e855cabULL,
+	0x673cbdbdcebd8173ULL, 0xba8f5d5d695dd234ULL, 0x2090101040108050ULL,
+	0xf507f4f4f7f4f303ULL, 0x8bddcbcb0bcb16c0ULL, 0x7cd33e3ef83eedc6ULL,
+	0x0a2d050514052811ULL, 0xce78676781671fe6ULL, 0xd597e4e4b7e47353ULL,
+	0x4e0227279c2725bbULL, 0x8273414119413258ULL, 0x0ba78b8b168b2c9dULL,
+	0x53f6a7a7a6a75101ULL, 0xfab27d7de97dcf94ULL, 0x374995956e95dcfbULL,
+	0xad56d8d847d88e9fULL, 0xeb70fbfbcbfb8b30ULL, 0xc1cdeeee9fee2371ULL,
+	0xf8bb7c7ced7cc791ULL, 0xcc716666856617e3ULL, 0xa77bdddd53dda68eULL,
+	0x2eaf17175c17b84bULL, 0x8e45474701470246ULL, 0x211a9e9e429e84dcULL,
+	0x89d4caca0fca1ec5ULL, 0x5a582d2db42d7599ULL, 0x632ebfbfc6bf9179ULL,
+	0x0e3f07071c07381bULL, 0x47acadad8ead0123ULL, 0xb4b05a5a755aea2fULL,
+	0x1bef838336836cb5ULL, 0x66b63333cc3385ffULL, 0xc65c636391633ff2ULL,
+	0x041202020802100aULL, 0x4993aaaa92aa3938ULL, 0xe2de7171d971afa8ULL,
+	0x8dc6c8c807c80ecfULL, 0x32d119196419c87dULL, 0x923b494939497270ULL,
+	0xaf5fd9d943d9869aULL, 0xf931f2f2eff2c31dULL, 0xdba8e3e3abe34b48ULL,
+	0xb6b95b5b715be22aULL, 0x0dbc88881a883492ULL, 0x293e9a9a529aa4c8ULL,
+	0x4c0b262698262dbeULL, 0x64bf3232c8328dfaULL, 0x7d59b0b0fab0e94aULL,
+	0xcff2e9e983e91b6aULL, 0x1e770f0f3c0f7833ULL, 0xb733d5d573d5e6a6ULL,
+	0x1df480803a8074baULL, 0x6127bebec2be997cULL, 0x87ebcdcd13cd26deULL,
+	0x68893434d034bde4ULL, 0x903248483d487a75ULL, 0xe354ffffdbffab24ULL,
+	0xf48d7a7af57af78fULL, 0x3d6490907a90f4eaULL, 0xbe9d5f5f615fc23eULL,
+	0x403d202080201da0ULL, 0xd00f6868bd6867d5ULL, 0x34ca1a1a681ad072ULL,
+	0x41b7aeae82ae192cULL, 0x757db4b4eab4c95eULL, 0xa8ce54544d549a19ULL,
+	0x3b7f93937693ece5ULL, 0x442f222288220daaULL, 0xc86364648d6407e9ULL,
+	0xff2af1f1e3f1db12ULL, 0xe6cc7373d173bfa2ULL, 0x248212124812905aULL,
+	0x807a40401d403a5dULL, 0x1048080820084028ULL, 0x9b95c3c32bc356e8ULL,
+	0xc5dfecec97ec337bULL, 0xab4ddbdb4bdb9690ULL, 0x5fc0a1a1bea1611fULL,
+	0x07918d8d0e8d1c83ULL, 0x7ac83d3df43df5c9ULL, 0x335b97976697ccf1ULL,
+	0x0000000000000000ULL, 0x83f9cfcf1bcf36d4ULL, 0x566e2b2bac2b4587ULL,
+	0xece17676c57697b3ULL, 0x19e68282328264b0ULL, 0xb128d6d67fd6fea9ULL,
+	0x36c31b1b6c1bd877ULL, 0x7774b5b5eeb5c15bULL, 0x43beafaf86af1129ULL,
+	0xd41d6a6ab56a77dfULL, 0xa0ea50505d50ba0dULL, 0x8a5745450945124cULL,
+	0xfb38f3f3ebf3cb18ULL, 0x60ad3030c0309df0ULL, 0xc3c4efef9bef2b74ULL,
+	0x7eda3f3ffc3fe5c3ULL, 0xaac755554955921cULL, 0x59dba2a2b2a27910ULL,
+	0xc9e9eaea8fea0365ULL, 0xca6a656589650fecULL, 0x6903babad2bab968ULL,
+	0x5e4a2f2fbc2f6593ULL, 0x9d8ec0c027c04ee7ULL, 0xa160dede5fdebe81ULL,
+	0x38fc1c1c701ce06cULL, 0xe746fdfdd3fdbb2eULL, 0x9a1f4d4d294d5264ULL,
+	0x397692927292e4e0ULL, 0xeafa7575c9758fbcULL, 0x0c3606061806301eULL,
+	0x09ae8a8a128a2498ULL, 0x794bb2b2f2b2f940ULL, 0xd185e6e6bfe66359ULL,
+	0x1c7e0e0e380e7036ULL, 0x3ee71f1f7c1ff863ULL, 0xc4556262956237f7ULL,
+	0xb53ad4d477d4eea3ULL, 0x4d81a8a89aa82932ULL, 0x315296966296c4f4ULL,
+	0xef62f9f9c3f99b3aULL, 0x97a3c5c533c566f6ULL, 0x4a102525942535b1ULL,
+	0xb2ab59597959f220ULL, 0x15d084842a8454aeULL, 0xe4c57272d572b7a7ULL,
+	0x72ec3939e439d5ddULL, 0x98164c4c2d4c5a61ULL, 0xbc945e5e655eca3bULL,
+	0xf09f7878fd78e785ULL, 0x70e53838e038ddd8ULL, 0x05988c8c0a8c1486ULL,
+	0xbf17d1d163d1c6b2ULL, 0x57e4a5a5aea5410bULL, 0xd9a1e2e2afe2434dULL,
+	0xc24e616199612ff8ULL, 0x7b42b3b3f6b3f145ULL, 0x42342121842115a5ULL,
+	0x25089c9c4a9c94d6ULL, 0x3cee1e1e781ef066ULL, 0x8661434311432252ULL,
+	0x93b1c7c73bc776fcULL, 0xe54ffcfcd7fcb32bULL, 0x0824040410042014ULL,
+	0xa2e351515951b208ULL, 0x2f2599995e99bcc7ULL, 0xda226d6da96d4fc4ULL,
+	0x1a650d0d340d6839ULL, 0xe979fafacffa8335ULL, 0xa369dfdf5bdfb684ULL,
+	0xfca97e7ee57ed79bULL, 0x4819242490243db4ULL, 0x76fe3b3bec3bc5d7ULL,
+	0x4b9aabab96ab313dULL, 0x81f0cece1fce3ed1ULL, 0x2299111144118855ULL,
+	0x03838f8f068f0c89ULL, 0x9c044e4e254e4a6bULL, 0x7366b7b7e6b7d151ULL,
+	0xcbe0ebeb8beb0b60ULL, 0x78c13c3cf03cfdccULL, 0x1ffd81813e817cbfULL,
+	0x354094946a94d4feULL, 0xf31cf7f7fbf7eb0cULL, 0x6f18b9b9deb9a167ULL,
+	0x268b13134c13985fULL, 0x58512c2cb02c7d9cULL, 0xbb05d3d36bd3d6b8ULL,
+	0xd38ce7e7bbe76b5cULL, 0xdc396e6ea56e57cbULL, 0x95aac4c437c46ef3ULL,
+	0x061b03030c03180fULL, 0xacdc565645568a13ULL, 0x885e44440d441a49ULL,
+	0xfea07f7fe17fdf9eULL, 0x4f88a9a99ea92137ULL, 0x54672a2aa82a4d82ULL,
+	0x6b0abbbbd6bbb16dULL, 0x9f87c1c123c146e2ULL, 0xa6f153535153a202ULL,
+	0xa572dcdc57dcae8bULL, 0x16530b0b2c0b5827ULL, 0x27019d9d4e9d9cd3ULL,
+	0xd82b6c6cad6c47c1ULL, 0x62a43131c43195f5ULL, 0xe8f37474cd7487b9ULL,
+	0xf115f6f6fff6e309ULL, 0x8c4c464605460a43ULL, 0x45a5acac8aac0926ULL,
+	0x0fb589891e893c97ULL, 0x28b414145014a044ULL, 0xdfbae1e1a3e15b42ULL,
+	0x2ca616165816b04eULL, 0x74f73a3ae83acdd2ULL, 0xd2066969b9696fd0ULL,
+	0x124109092409482dULL, 0xe0d77070dd70a7adULL, 0x716fb6b6e2b6d954ULL,
+	0xbd1ed0d067d0ceb7ULL, 0xc7d6eded93ed3b7eULL, 0x85e2cccc17cc2edbULL,
+	0x8468424215422a57ULL, 0x2d2c98985a98b4c2ULL, 0x55eda4a4aaa4490eULL,
+	0x50752828a0285d88ULL, 0xb8865c5c6d5cda31ULL, 0xed6bf8f8c7f8933fULL,
+	0x11c28686228644a4ULL,
+};
+
+static const u64 C3[256] = {
+	0x7830d818186018c0ULL, 0xaf462623238c2305ULL, 0xf991b8c6c63fc67eULL,
+	0x6fcdfbe8e887e813ULL, 0xa113cb878726874cULL, 0x626d11b8b8dab8a9ULL,
+	0x0502090101040108ULL, 0x6e9e0d4f4f214f42ULL, 0xee6c9b3636d836adULL,
+	0x0451ffa6a6a2a659ULL, 0xbdb90cd2d26fd2deULL, 0x06f70ef5f5f3f5fbULL,
+	0x80f2967979f979efULL, 0xcede306f6fa16f5fULL, 0xef3f6d91917e91fcULL,
+	0x07a4f852525552aaULL, 0xfdc04760609d6027ULL, 0x766535bcbccabc89ULL,
+	0xcd2b379b9b569bacULL, 0x8c018a8e8e028e04ULL, 0x155bd2a3a3b6a371ULL,
+	0x3c186c0c0c300c60ULL, 0x8af6847b7bf17bffULL, 0xe16a803535d435b5ULL,
+	0x693af51d1d741de8ULL, 0x47ddb3e0e0a7e053ULL, 0xacb321d7d77bd7f6ULL,
+	0xed999cc2c22fc25eULL, 0x965c432e2eb82e6dULL, 0x7a96294b4b314b62ULL,
+	0x21e15dfefedffea3ULL, 0x16aed55757415782ULL, 0x412abd15155415a8ULL,
+	0xb6eee87777c1779fULL, 0xeb6e923737dc37a5ULL, 0x56d79ee5e5b3e57bULL,
+	0xd923139f9f469f8cULL, 0x17fd23f0f0e7f0d3ULL, 0x7f94204a4a354a6aULL,
+	0x95a944dada4fda9eULL, 0x25b0a258587d58faULL, 0xca8fcfc9c903c906ULL,
+	0x8d527c2929a42955ULL, 0x22145a0a0a280a50ULL, 0x4f7f50b1b1feb1e1ULL,
+	0x1a5dc9a0a0baa069ULL, 0xdad6146b6bb16b7fULL, 0xab17d985852e855cULL,
+	0x73673cbdbdcebd81ULL, 0x34ba8f5d5d695dd2ULL, 0x5020901010401080ULL,
+	0x03f507f4f4f7f4f3ULL, 0xc08bddcbcb0bcb16ULL, 0xc67cd33e3ef83eedULL,
+	0x110a2d0505140528ULL, 0xe6ce78676781671fULL, 0x53d597e4e4b7e473ULL,
+	0xbb4e0227279c2725ULL, 0x5882734141194132ULL, 0x9d0ba78b8b168b2cULL,
+	0x0153f6a7a7a6a751ULL, 0x94fab27d7de97dcfULL, 0xfb374995956e95dcULL,
+	0x9fad56d8d847d88eULL, 0x30eb70fbfbcbfb8bULL, 0x71c1cdeeee9fee23ULL,
+	0x91f8bb7c7ced7cc7ULL, 0xe3cc716666856617ULL, 0x8ea77bdddd53dda6ULL,
+	0x4b2eaf17175c17b8ULL, 0x468e454747014702ULL, 0xdc211a9e9e429e84ULL,
+	0xc589d4caca0fca1eULL, 0x995a582d2db42d75ULL, 0x79632ebfbfc6bf91ULL,
+	0x1b0e3f07071c0738ULL, 0x2347acadad8ead01ULL, 0x2fb4b05a5a755aeaULL,
+	0xb51bef838336836cULL, 0xff66b63333cc3385ULL, 0xf2c65c636391633fULL,
+	0x0a04120202080210ULL, 0x384993aaaa92aa39ULL, 0xa8e2de7171d971afULL,
+	0xcf8dc6c8c807c80eULL, 0x7d32d119196419c8ULL, 0x70923b4949394972ULL,
+	0x9aaf5fd9d943d986ULL, 0x1df931f2f2eff2c3ULL, 0x48dba8e3e3abe34bULL,
+	0x2ab6b95b5b715be2ULL, 0x920dbc88881a8834ULL, 0xc8293e9a9a529aa4ULL,
+	0xbe4c0b262698262dULL, 0xfa64bf3232c8328dULL, 0x4a7d59b0b0fab0e9ULL,
+	0x6acff2e9e983e91bULL, 0x331e770f0f3c0f78ULL, 0xa6b733d5d573d5e6ULL,
+	0xba1df480803a8074ULL, 0x7c6127bebec2be99ULL, 0xde87ebcdcd13cd26ULL,
+	0xe468893434d034bdULL, 0x75903248483d487aULL, 0x24e354ffffdbffabULL,
+	0x8ff48d7a7af57af7ULL, 0xea3d6490907a90f4ULL, 0x3ebe9d5f5f615fc2ULL,
+	0xa0403d202080201dULL, 0xd5d00f6868bd6867ULL, 0x7234ca1a1a681ad0ULL,
+	0x2c41b7aeae82ae19ULL, 0x5e757db4b4eab4c9ULL, 0x19a8ce54544d549aULL,
+	0xe53b7f93937693ecULL, 0xaa442f222288220dULL, 0xe9c86364648d6407ULL,
+	0x12ff2af1f1e3f1dbULL, 0xa2e6cc7373d173bfULL, 0x5a24821212481290ULL,
+	0x5d807a40401d403aULL, 0x2810480808200840ULL, 0xe89b95c3c32bc356ULL,
+	0x7bc5dfecec97ec33ULL, 0x90ab4ddbdb4bdb96ULL, 0x1f5fc0a1a1bea161ULL,
+	0x8307918d8d0e8d1cULL, 0xc97ac83d3df43df5ULL, 0xf1335b97976697ccULL,
+	0x0000000000000000ULL, 0xd483f9cfcf1bcf36ULL, 0x87566e2b2bac2b45ULL,
+	0xb3ece17676c57697ULL, 0xb019e68282328264ULL, 0xa9b128d6d67fd6feULL,
+	0x7736c31b1b6c1bd8ULL, 0x5b7774b5b5eeb5c1ULL, 0x2943beafaf86af11ULL,
+	0xdfd41d6a6ab56a77ULL, 0x0da0ea50505d50baULL, 0x4c8a574545094512ULL,
+	0x18fb38f3f3ebf3cbULL, 0xf060ad3030c0309dULL, 0x74c3c4efef9bef2bULL,
+	0xc37eda3f3ffc3fe5ULL, 0x1caac75555495592ULL, 0x1059dba2a2b2a279ULL,
+	0x65c9e9eaea8fea03ULL, 0xecca6a656589650fULL, 0x686903babad2bab9ULL,
+	0x935e4a2f2fbc2f65ULL, 0xe79d8ec0c027c04eULL, 0x81a160dede5fdebeULL,
+	0x6c38fc1c1c701ce0ULL, 0x2ee746fdfdd3fdbbULL, 0x649a1f4d4d294d52ULL,
+	0xe0397692927292e4ULL, 0xbceafa7575c9758fULL, 0x1e0c360606180630ULL,
+	0x9809ae8a8a128a24ULL, 0x40794bb2b2f2b2f9ULL, 0x59d185e6e6bfe663ULL,
+	0x361c7e0e0e380e70ULL, 0x633ee71f1f7c1ff8ULL, 0xf7c4556262956237ULL,
+	0xa3b53ad4d477d4eeULL, 0x324d81a8a89aa829ULL, 0xf4315296966296c4ULL,
+	0x3aef62f9f9c3f99bULL, 0xf697a3c5c533c566ULL, 0xb14a102525942535ULL,
+	0x20b2ab59597959f2ULL, 0xae15d084842a8454ULL, 0xa7e4c57272d572b7ULL,
+	0xdd72ec3939e439d5ULL, 0x6198164c4c2d4c5aULL, 0x3bbc945e5e655ecaULL,
+	0x85f09f7878fd78e7ULL, 0xd870e53838e038ddULL, 0x8605988c8c0a8c14ULL,
+	0xb2bf17d1d163d1c6ULL, 0x0b57e4a5a5aea541ULL, 0x4dd9a1e2e2afe243ULL,
+	0xf8c24e616199612fULL, 0x457b42b3b3f6b3f1ULL, 0xa542342121842115ULL,
+	0xd625089c9c4a9c94ULL, 0x663cee1e1e781ef0ULL, 0x5286614343114322ULL,
+	0xfc93b1c7c73bc776ULL, 0x2be54ffcfcd7fcb3ULL, 0x1408240404100420ULL,
+	0x08a2e351515951b2ULL, 0xc72f2599995e99bcULL, 0xc4da226d6da96d4fULL,
+	0x391a650d0d340d68ULL, 0x35e979fafacffa83ULL, 0x84a369dfdf5bdfb6ULL,
+	0x9bfca97e7ee57ed7ULL, 0xb44819242490243dULL, 0xd776fe3b3bec3bc5ULL,
+	0x3d4b9aabab96ab31ULL, 0xd181f0cece1fce3eULL, 0x5522991111441188ULL,
+	0x8903838f8f068f0cULL, 0x6b9c044e4e254e4aULL, 0x517366b7b7e6b7d1ULL,
+	0x60cbe0ebeb8beb0bULL, 0xcc78c13c3cf03cfdULL, 0xbf1ffd81813e817cULL,
+	0xfe354094946a94d4ULL, 0x0cf31cf7f7fbf7ebULL, 0x676f18b9b9deb9a1ULL,
+	0x5f268b13134c1398ULL, 0x9c58512c2cb02c7dULL, 0xb8bb05d3d36bd3d6ULL,
+	0x5cd38ce7e7bbe76bULL, 0xcbdc396e6ea56e57ULL, 0xf395aac4c437c46eULL,
+	0x0f061b03030c0318ULL, 0x13acdc565645568aULL, 0x49885e44440d441aULL,
+	0x9efea07f7fe17fdfULL, 0x374f88a9a99ea921ULL, 0x8254672a2aa82a4dULL,
+	0x6d6b0abbbbd6bbb1ULL, 0xe29f87c1c123c146ULL, 0x02a6f153535153a2ULL,
+	0x8ba572dcdc57dcaeULL, 0x2716530b0b2c0b58ULL, 0xd327019d9d4e9d9cULL,
+	0xc1d82b6c6cad6c47ULL, 0xf562a43131c43195ULL, 0xb9e8f37474cd7487ULL,
+	0x09f115f6f6fff6e3ULL, 0x438c4c464605460aULL, 0x2645a5acac8aac09ULL,
+	0x970fb589891e893cULL, 0x4428b414145014a0ULL, 0x42dfbae1e1a3e15bULL,
+	0x4e2ca616165816b0ULL, 0xd274f73a3ae83acdULL, 0xd0d2066969b9696fULL,
+	0x2d12410909240948ULL, 0xade0d77070dd70a7ULL, 0x54716fb6b6e2b6d9ULL,
+	0xb7bd1ed0d067d0ceULL, 0x7ec7d6eded93ed3bULL, 0xdb85e2cccc17cc2eULL,
+	0x578468424215422aULL, 0xc22d2c98985a98b4ULL, 0x0e55eda4a4aaa449ULL,
+	0x8850752828a0285dULL, 0x31b8865c5c6d5cdaULL, 0x3fed6bf8f8c7f893ULL,
+	0xa411c28686228644ULL,
+};
+
+static const u64 C4[256] = {
+	0xc07830d818186018ULL, 0x05af462623238c23ULL, 0x7ef991b8c6c63fc6ULL,
+	0x136fcdfbe8e887e8ULL, 0x4ca113cb87872687ULL, 0xa9626d11b8b8dab8ULL,
+	0x0805020901010401ULL, 0x426e9e0d4f4f214fULL, 0xadee6c9b3636d836ULL,
+	0x590451ffa6a6a2a6ULL, 0xdebdb90cd2d26fd2ULL, 0xfb06f70ef5f5f3f5ULL,
+	0xef80f2967979f979ULL, 0x5fcede306f6fa16fULL, 0xfcef3f6d91917e91ULL,
+	0xaa07a4f852525552ULL, 0x27fdc04760609d60ULL, 0x89766535bcbccabcULL,
+	0xaccd2b379b9b569bULL, 0x048c018a8e8e028eULL, 0x71155bd2a3a3b6a3ULL,
+	0x603c186c0c0c300cULL, 0xff8af6847b7bf17bULL, 0xb5e16a803535d435ULL,
+	0xe8693af51d1d741dULL, 0x5347ddb3e0e0a7e0ULL, 0xf6acb321d7d77bd7ULL,
+	0x5eed999cc2c22fc2ULL, 0x6d965c432e2eb82eULL, 0x627a96294b4b314bULL,
+	0xa321e15dfefedffeULL, 0x8216aed557574157ULL, 0xa8412abd15155415ULL,
+	0x9fb6eee87777c177ULL, 0xa5eb6e923737dc37ULL, 0x7b56d79ee5e5b3e5ULL,
+	0x8cd923139f9f469fULL, 0xd317fd23f0f0e7f0ULL, 0x6a7f94204a4a354aULL,
+	0x9e95a944dada4fdaULL, 0xfa25b0a258587d58ULL, 0x06ca8fcfc9c903c9ULL,
+	0x558d527c2929a429ULL, 0x5022145a0a0a280aULL, 0xe14f7f50b1b1feb1ULL,
+	0x691a5dc9a0a0baa0ULL, 0x7fdad6146b6bb16bULL, 0x5cab17d985852e85ULL,
+	0x8173673cbdbdcebdULL, 0xd234ba8f5d5d695dULL, 0x8050209010104010ULL,
+	0xf303f507f4f4f7f4ULL, 0x16c08bddcbcb0bcbULL, 0xedc67cd33e3ef83eULL,
+	0x28110a2d05051405ULL, 0x1fe6ce7867678167ULL, 0x7353d597e4e4b7e4ULL,
+	0x25bb4e0227279c27ULL, 0x3258827341411941ULL, 0x2c9d0ba78b8b168bULL,
+	0x510153f6a7a7a6a7ULL, 0xcf94fab27d7de97dULL, 0xdcfb374995956e95ULL,
+	0x8e9fad56d8d847d8ULL, 0x8b30eb70fbfbcbfbULL, 0x2371c1cdeeee9feeULL,
+	0xc791f8bb7c7ced7cULL, 0x17e3cc7166668566ULL, 0xa68ea77bdddd53ddULL,
+	0xb84b2eaf17175c17ULL, 0x02468e4547470147ULL, 0x84dc211a9e9e429eULL,
+	0x1ec589d4caca0fcaULL, 0x75995a582d2db42dULL, 0x9179632ebfbfc6bfULL,
+	0x381b0e3f07071c07ULL, 0x012347acadad8eadULL, 0xea2fb4b05a5a755aULL,
+	0x6cb51bef83833683ULL, 0x85ff66b63333cc33ULL, 0x3ff2c65c63639163ULL,
+	0x100a041202020802ULL, 0x39384993aaaa92aaULL, 0xafa8e2de7171d971ULL,
+	0x0ecf8dc6c8c807c8ULL, 0xc87d32d119196419ULL, 0x7270923b49493949ULL,
+	0x869aaf5fd9d943d9ULL, 0xc31df931f2f2eff2ULL, 0x4b48dba8e3e3abe3ULL,
+	0xe22ab6b95b5b715bULL, 0x34920dbc88881a88ULL, 0xa4c8293e9a9a529aULL,
+	0x2dbe4c0b26269826ULL, 0x8dfa64bf3232c832ULL, 0xe94a7d59b0b0fab0ULL,
+	0x1b6acff2e9e983e9ULL, 0x78331e770f0f3c0fULL, 0xe6a6b733d5d573d5ULL,
+	0x74ba1df480803a80ULL, 0x997c6127bebec2beULL, 0x26de87ebcdcd13cdULL,
+	0xbde468893434d034ULL, 0x7a75903248483d48ULL, 0xab24e354ffffdbffULL,
+	0xf78ff48d7a7af57aULL, 0xf4ea3d6490907a90ULL, 0xc23ebe9d5f5f615fULL,
+	0x1da0403d20208020ULL, 0x67d5d00f6868bd68ULL, 0xd07234ca1a1a681aULL,
+	0x192c41b7aeae82aeULL, 0xc95e757db4b4eab4ULL, 0x9a19a8ce54544d54ULL,
+	0xece53b7f93937693ULL, 0x0daa442f22228822ULL, 0x07e9c86364648d64ULL,
+	0xdb12ff2af1f1e3f1ULL, 0xbfa2e6cc7373d173ULL, 0x905a248212124812ULL,
+	0x3a5d807a40401d40ULL, 0x4028104808082008ULL, 0x56e89b95c3c32bc3ULL,
+	0x337bc5dfecec97ecULL, 0x9690ab4ddbdb4bdbULL, 0x611f5fc0a1a1bea1ULL,
+	0x1c8307918d8d0e8dULL, 0xf5c97ac83d3df43dULL, 0xccf1335b97976697ULL,
+	0x0000000000000000ULL, 0x36d483f9cfcf1bcfULL, 0x4587566e2b2bac2bULL,
+	0x97b3ece17676c576ULL, 0x64b019e682823282ULL, 0xfea9b128d6d67fd6ULL,
+	0xd87736c31b1b6c1bULL, 0xc15b7774b5b5eeb5ULL, 0x112943beafaf86afULL,
+	0x77dfd41d6a6ab56aULL, 0xba0da0ea50505d50ULL, 0x124c8a5745450945ULL,
+	0xcb18fb38f3f3ebf3ULL, 0x9df060ad3030c030ULL, 0x2b74c3c4efef9befULL,
+	0xe5c37eda3f3ffc3fULL, 0x921caac755554955ULL, 0x791059dba2a2b2a2ULL,
+	0x0365c9e9eaea8feaULL, 0x0fecca6a65658965ULL, 0xb9686903babad2baULL,
+	0x65935e4a2f2fbc2fULL, 0x4ee79d8ec0c027c0ULL, 0xbe81a160dede5fdeULL,
+	0xe06c38fc1c1c701cULL, 0xbb2ee746fdfdd3fdULL, 0x52649a1f4d4d294dULL,
+	0xe4e0397692927292ULL, 0x8fbceafa7575c975ULL, 0x301e0c3606061806ULL,
+	0x249809ae8a8a128aULL, 0xf940794bb2b2f2b2ULL, 0x6359d185e6e6bfe6ULL,
+	0x70361c7e0e0e380eULL, 0xf8633ee71f1f7c1fULL, 0x37f7c45562629562ULL,
+	0xeea3b53ad4d477d4ULL, 0x29324d81a8a89aa8ULL, 0xc4f4315296966296ULL,
+	0x9b3aef62f9f9c3f9ULL, 0x66f697a3c5c533c5ULL, 0x35b14a1025259425ULL,
+	0xf220b2ab59597959ULL, 0x54ae15d084842a84ULL, 0xb7a7e4c57272d572ULL,
+	0xd5dd72ec3939e439ULL, 0x5a6198164c4c2d4cULL, 0xca3bbc945e5e655eULL,
+	0xe785f09f7878fd78ULL, 0xddd870e53838e038ULL, 0x148605988c8c0a8cULL,
+	0xc6b2bf17d1d163d1ULL, 0x410b57e4a5a5aea5ULL, 0x434dd9a1e2e2afe2ULL,
+	0x2ff8c24e61619961ULL, 0xf1457b42b3b3f6b3ULL, 0x15a5423421218421ULL,
+	0x94d625089c9c4a9cULL, 0xf0663cee1e1e781eULL, 0x2252866143431143ULL,
+	0x76fc93b1c7c73bc7ULL, 0xb32be54ffcfcd7fcULL, 0x2014082404041004ULL,
+	0xb208a2e351515951ULL, 0xbcc72f2599995e99ULL, 0x4fc4da226d6da96dULL,
+	0x68391a650d0d340dULL, 0x8335e979fafacffaULL, 0xb684a369dfdf5bdfULL,
+	0xd79bfca97e7ee57eULL, 0x3db4481924249024ULL, 0xc5d776fe3b3bec3bULL,
+	0x313d4b9aabab96abULL, 0x3ed181f0cece1fceULL, 0x8855229911114411ULL,
+	0x0c8903838f8f068fULL, 0x4a6b9c044e4e254eULL, 0xd1517366b7b7e6b7ULL,
+	0x0b60cbe0ebeb8bebULL, 0xfdcc78c13c3cf03cULL, 0x7cbf1ffd81813e81ULL,
+	0xd4fe354094946a94ULL, 0xeb0cf31cf7f7fbf7ULL, 0xa1676f18b9b9deb9ULL,
+	0x985f268b13134c13ULL, 0x7d9c58512c2cb02cULL, 0xd6b8bb05d3d36bd3ULL,
+	0x6b5cd38ce7e7bbe7ULL, 0x57cbdc396e6ea56eULL, 0x6ef395aac4c437c4ULL,
+	0x180f061b03030c03ULL, 0x8a13acdc56564556ULL, 0x1a49885e44440d44ULL,
+	0xdf9efea07f7fe17fULL, 0x21374f88a9a99ea9ULL, 0x4d8254672a2aa82aULL,
+	0xb16d6b0abbbbd6bbULL, 0x46e29f87c1c123c1ULL, 0xa202a6f153535153ULL,
+	0xae8ba572dcdc57dcULL, 0x582716530b0b2c0bULL, 0x9cd327019d9d4e9dULL,
+	0x47c1d82b6c6cad6cULL, 0x95f562a43131c431ULL, 0x87b9e8f37474cd74ULL,
+	0xe309f115f6f6fff6ULL, 0x0a438c4c46460546ULL, 0x092645a5acac8aacULL,
+	0x3c970fb589891e89ULL, 0xa04428b414145014ULL, 0x5b42dfbae1e1a3e1ULL,
+	0xb04e2ca616165816ULL, 0xcdd274f73a3ae83aULL, 0x6fd0d2066969b969ULL,
+	0x482d124109092409ULL, 0xa7ade0d77070dd70ULL, 0xd954716fb6b6e2b6ULL,
+	0xceb7bd1ed0d067d0ULL, 0x3b7ec7d6eded93edULL, 0x2edb85e2cccc17ccULL,
+	0x2a57846842421542ULL, 0xb4c22d2c98985a98ULL, 0x490e55eda4a4aaa4ULL,
+	0x5d8850752828a028ULL, 0xda31b8865c5c6d5cULL, 0x933fed6bf8f8c7f8ULL,
+	0x44a411c286862286ULL,
+};
+
+static const u64 C5[256] = {
+	0x18c07830d8181860ULL, 0x2305af462623238cULL, 0xc67ef991b8c6c63fULL,
+	0xe8136fcdfbe8e887ULL, 0x874ca113cb878726ULL, 0xb8a9626d11b8b8daULL,
+	0x0108050209010104ULL, 0x4f426e9e0d4f4f21ULL, 0x36adee6c9b3636d8ULL,
+	0xa6590451ffa6a6a2ULL, 0xd2debdb90cd2d26fULL, 0xf5fb06f70ef5f5f3ULL,
+	0x79ef80f2967979f9ULL, 0x6f5fcede306f6fa1ULL, 0x91fcef3f6d91917eULL,
+	0x52aa07a4f8525255ULL, 0x6027fdc04760609dULL, 0xbc89766535bcbccaULL,
+	0x9baccd2b379b9b56ULL, 0x8e048c018a8e8e02ULL, 0xa371155bd2a3a3b6ULL,
+	0x0c603c186c0c0c30ULL, 0x7bff8af6847b7bf1ULL, 0x35b5e16a803535d4ULL,
+	0x1de8693af51d1d74ULL, 0xe05347ddb3e0e0a7ULL, 0xd7f6acb321d7d77bULL,
+	0xc25eed999cc2c22fULL, 0x2e6d965c432e2eb8ULL, 0x4b627a96294b4b31ULL,
+	0xfea321e15dfefedfULL, 0x578216aed5575741ULL, 0x15a8412abd151554ULL,
+	0x779fb6eee87777c1ULL, 0x37a5eb6e923737dcULL, 0xe57b56d79ee5e5b3ULL,
+	0x9f8cd923139f9f46ULL, 0xf0d317fd23f0f0e7ULL, 0x4a6a7f94204a4a35ULL,
+	0xda9e95a944dada4fULL, 0x58fa25b0a258587dULL, 0xc906ca8fcfc9c903ULL,
+	0x29558d527c2929a4ULL, 0x0a5022145a0a0a28ULL, 0xb1e14f7f50b1b1feULL,
+	0xa0691a5dc9a0a0baULL, 0x6b7fdad6146b6bb1ULL, 0x855cab17d985852eULL,
+	0xbd8173673cbdbdceULL, 0x5dd234ba8f5d5d69ULL, 0x1080502090101040ULL,
+	0xf4f303f507f4f4f7ULL, 0xcb16c08bddcbcb0bULL, 0x3eedc67cd33e3ef8ULL,
+	0x0528110a2d050514ULL, 0x671fe6ce78676781ULL, 0xe47353d597e4e4b7ULL,
+	0x2725bb4e0227279cULL, 0x4132588273414119ULL, 0x8b2c9d0ba78b8b16ULL,
+	0xa7510153f6a7a7a6ULL, 0x7dcf94fab27d7de9ULL, 0x95dcfb374995956eULL,
+	0xd88e9fad56d8d847ULL, 0xfb8b30eb70fbfbcbULL, 0xee2371c1cdeeee9fULL,
+	0x7cc791f8bb7c7cedULL, 0x6617e3cc71666685ULL, 0xdda68ea77bdddd53ULL,
+	0x17b84b2eaf17175cULL, 0x4702468e45474701ULL, 0x9e84dc211a9e9e42ULL,
+	0xca1ec589d4caca0fULL, 0x2d75995a582d2db4ULL, 0xbf9179632ebfbfc6ULL,
+	0x07381b0e3f07071cULL, 0xad012347acadad8eULL, 0x5aea2fb4b05a5a75ULL,
+	0x836cb51bef838336ULL, 0x3385ff66b63333ccULL, 0x633ff2c65c636391ULL,
+	0x02100a0412020208ULL, 0xaa39384993aaaa92ULL, 0x71afa8e2de7171d9ULL,
+	0xc80ecf8dc6c8c807ULL, 0x19c87d32d1191964ULL, 0x497270923b494939ULL,
+	0xd9869aaf5fd9d943ULL, 0xf2c31df931f2f2efULL, 0xe34b48dba8e3e3abULL,
+	0x5be22ab6b95b5b71ULL, 0x8834920dbc88881aULL, 0x9aa4c8293e9a9a52ULL,
+	0x262dbe4c0b262698ULL, 0x328dfa64bf3232c8ULL, 0xb0e94a7d59b0b0faULL,
+	0xe91b6acff2e9e983ULL, 0x0f78331e770f0f3cULL, 0xd5e6a6b733d5d573ULL,
+	0x8074ba1df480803aULL, 0xbe997c6127bebec2ULL, 0xcd26de87ebcdcd13ULL,
+	0x34bde468893434d0ULL, 0x487a75903248483dULL, 0xffab24e354ffffdbULL,
+	0x7af78ff48d7a7af5ULL, 0x90f4ea3d6490907aULL, 0x5fc23ebe9d5f5f61ULL,
+	0x201da0403d202080ULL, 0x6867d5d00f6868bdULL, 0x1ad07234ca1a1a68ULL,
+	0xae192c41b7aeae82ULL, 0xb4c95e757db4b4eaULL, 0x549a19a8ce54544dULL,
+	0x93ece53b7f939376ULL, 0x220daa442f222288ULL, 0x6407e9c86364648dULL,
+	0xf1db12ff2af1f1e3ULL, 0x73bfa2e6cc7373d1ULL, 0x12905a2482121248ULL,
+	0x403a5d807a40401dULL, 0x0840281048080820ULL, 0xc356e89b95c3c32bULL,
+	0xec337bc5dfecec97ULL, 0xdb9690ab4ddbdb4bULL, 0xa1611f5fc0a1a1beULL,
+	0x8d1c8307918d8d0eULL, 0x3df5c97ac83d3df4ULL, 0x97ccf1335b979766ULL,
+	0x0000000000000000ULL, 0xcf36d483f9cfcf1bULL, 0x2b4587566e2b2bacULL,
+	0x7697b3ece17676c5ULL, 0x8264b019e6828232ULL, 0xd6fea9b128d6d67fULL,
+	0x1bd87736c31b1b6cULL, 0xb5c15b7774b5b5eeULL, 0xaf112943beafaf86ULL,
+	0x6a77dfd41d6a6ab5ULL, 0x50ba0da0ea50505dULL, 0x45124c8a57454509ULL,
+	0xf3cb18fb38f3f3ebULL, 0x309df060ad3030c0ULL, 0xef2b74c3c4efef9bULL,
+	0x3fe5c37eda3f3ffcULL, 0x55921caac7555549ULL, 0xa2791059dba2a2b2ULL,
+	0xea0365c9e9eaea8fULL, 0x650fecca6a656589ULL, 0xbab9686903babad2ULL,
+	0x2f65935e4a2f2fbcULL, 0xc04ee79d8ec0c027ULL, 0xdebe81a160dede5fULL,
+	0x1ce06c38fc1c1c70ULL, 0xfdbb2ee746fdfdd3ULL, 0x4d52649a1f4d4d29ULL,
+	0x92e4e03976929272ULL, 0x758fbceafa7575c9ULL, 0x06301e0c36060618ULL,
+	0x8a249809ae8a8a12ULL, 0xb2f940794bb2b2f2ULL, 0xe66359d185e6e6bfULL,
+	0x0e70361c7e0e0e38ULL, 0x1ff8633ee71f1f7cULL, 0x6237f7c455626295ULL,
+	0xd4eea3b53ad4d477ULL, 0xa829324d81a8a89aULL, 0x96c4f43152969662ULL,
+	0xf99b3aef62f9f9c3ULL, 0xc566f697a3c5c533ULL, 0x2535b14a10252594ULL,
+	0x59f220b2ab595979ULL, 0x8454ae15d084842aULL, 0x72b7a7e4c57272d5ULL,
+	0x39d5dd72ec3939e4ULL, 0x4c5a6198164c4c2dULL, 0x5eca3bbc945e5e65ULL,
+	0x78e785f09f7878fdULL, 0x38ddd870e53838e0ULL, 0x8c148605988c8c0aULL,
+	0xd1c6b2bf17d1d163ULL, 0xa5410b57e4a5a5aeULL, 0xe2434dd9a1e2e2afULL,
+	0x612ff8c24e616199ULL, 0xb3f1457b42b3b3f6ULL, 0x2115a54234212184ULL,
+	0x9c94d625089c9c4aULL, 0x1ef0663cee1e1e78ULL, 0x4322528661434311ULL,
+	0xc776fc93b1c7c73bULL, 0xfcb32be54ffcfcd7ULL, 0x0420140824040410ULL,
+	0x51b208a2e3515159ULL, 0x99bcc72f2599995eULL, 0x6d4fc4da226d6da9ULL,
+	0x0d68391a650d0d34ULL, 0xfa8335e979fafacfULL, 0xdfb684a369dfdf5bULL,
+	0x7ed79bfca97e7ee5ULL, 0x243db44819242490ULL, 0x3bc5d776fe3b3becULL,
+	0xab313d4b9aabab96ULL, 0xce3ed181f0cece1fULL, 0x1188552299111144ULL,
+	0x8f0c8903838f8f06ULL, 0x4e4a6b9c044e4e25ULL, 0xb7d1517366b7b7e6ULL,
+	0xeb0b60cbe0ebeb8bULL, 0x3cfdcc78c13c3cf0ULL, 0x817cbf1ffd81813eULL,
+	0x94d4fe354094946aULL, 0xf7eb0cf31cf7f7fbULL, 0xb9a1676f18b9b9deULL,
+	0x13985f268b13134cULL, 0x2c7d9c58512c2cb0ULL, 0xd3d6b8bb05d3d36bULL,
+	0xe76b5cd38ce7e7bbULL, 0x6e57cbdc396e6ea5ULL, 0xc46ef395aac4c437ULL,
+	0x03180f061b03030cULL, 0x568a13acdc565645ULL, 0x441a49885e44440dULL,
+	0x7fdf9efea07f7fe1ULL, 0xa921374f88a9a99eULL, 0x2a4d8254672a2aa8ULL,
+	0xbbb16d6b0abbbbd6ULL, 0xc146e29f87c1c123ULL, 0x53a202a6f1535351ULL,
+	0xdcae8ba572dcdc57ULL, 0x0b582716530b0b2cULL, 0x9d9cd327019d9d4eULL,
+	0x6c47c1d82b6c6cadULL, 0x3195f562a43131c4ULL, 0x7487b9e8f37474cdULL,
+	0xf6e309f115f6f6ffULL, 0x460a438c4c464605ULL, 0xac092645a5acac8aULL,
+	0x893c970fb589891eULL, 0x14a04428b4141450ULL, 0xe15b42dfbae1e1a3ULL,
+	0x16b04e2ca6161658ULL, 0x3acdd274f73a3ae8ULL, 0x696fd0d2066969b9ULL,
+	0x09482d1241090924ULL, 0x70a7ade0d77070ddULL, 0xb6d954716fb6b6e2ULL,
+	0xd0ceb7bd1ed0d067ULL, 0xed3b7ec7d6eded93ULL, 0xcc2edb85e2cccc17ULL,
+	0x422a578468424215ULL, 0x98b4c22d2c98985aULL, 0xa4490e55eda4a4aaULL,
+	0x285d8850752828a0ULL, 0x5cda31b8865c5c6dULL, 0xf8933fed6bf8f8c7ULL,
+	0x8644a411c2868622ULL,
+};
+
+static const u64 C6[256] = {
+	0x6018c07830d81818ULL, 0x8c2305af46262323ULL, 0x3fc67ef991b8c6c6ULL,
+	0x87e8136fcdfbe8e8ULL, 0x26874ca113cb8787ULL, 0xdab8a9626d11b8b8ULL,
+	0x0401080502090101ULL, 0x214f426e9e0d4f4fULL, 0xd836adee6c9b3636ULL,
+	0xa2a6590451ffa6a6ULL, 0x6fd2debdb90cd2d2ULL, 0xf3f5fb06f70ef5f5ULL,
+	0xf979ef80f2967979ULL, 0xa16f5fcede306f6fULL, 0x7e91fcef3f6d9191ULL,
+	0x5552aa07a4f85252ULL, 0x9d6027fdc0476060ULL, 0xcabc89766535bcbcULL,
+	0x569baccd2b379b9bULL, 0x028e048c018a8e8eULL, 0xb6a371155bd2a3a3ULL,
+	0x300c603c186c0c0cULL, 0xf17bff8af6847b7bULL, 0xd435b5e16a803535ULL,
+	0x741de8693af51d1dULL, 0xa7e05347ddb3e0e0ULL, 0x7bd7f6acb321d7d7ULL,
+	0x2fc25eed999cc2c2ULL, 0xb82e6d965c432e2eULL, 0x314b627a96294b4bULL,
+	0xdffea321e15dfefeULL, 0x41578216aed55757ULL, 0x5415a8412abd1515ULL,
+	0xc1779fb6eee87777ULL, 0xdc37a5eb6e923737ULL, 0xb3e57b56d79ee5e5ULL,
+	0x469f8cd923139f9fULL, 0xe7f0d317fd23f0f0ULL, 0x354a6a7f94204a4aULL,
+	0x4fda9e95a944dadaULL, 0x7d58fa25b0a25858ULL, 0x03c906ca8fcfc9c9ULL,
+	0xa429558d527c2929ULL, 0x280a5022145a0a0aULL, 0xfeb1e14f7f50b1b1ULL,
+	0xbaa0691a5dc9a0a0ULL, 0xb16b7fdad6146b6bULL, 0x2e855cab17d98585ULL,
+	0xcebd8173673cbdbdULL, 0x695dd234ba8f5d5dULL, 0x4010805020901010ULL,
+	0xf7f4f303f507f4f4ULL, 0x0bcb16c08bddcbcbULL, 0xf83eedc67cd33e3eULL,
+	0x140528110a2d0505ULL, 0x81671fe6ce786767ULL, 0xb7e47353d597e4e4ULL,
+	0x9c2725bb4e022727ULL, 0x1941325882734141ULL, 0x168b2c9d0ba78b8bULL,
+	0xa6a7510153f6a7a7ULL, 0xe97dcf94fab27d7dULL, 0x6e95dcfb37499595ULL,
+	0x47d88e9fad56d8d8ULL, 0xcbfb8b30eb70fbfbULL, 0x9fee2371c1cdeeeeULL,
+	0xed7cc791f8bb7c7cULL, 0x856617e3cc716666ULL, 0x53dda68ea77bddddULL,
+	0x5c17b84b2eaf1717ULL, 0x014702468e454747ULL, 0x429e84dc211a9e9eULL,
+	0x0fca1ec589d4cacaULL, 0xb42d75995a582d2dULL, 0xc6bf9179632ebfbfULL,
+	0x1c07381b0e3f0707ULL, 0x8ead012347acadadULL, 0x755aea2fb4b05a5aULL,
+	0x36836cb51bef8383ULL, 0xcc3385ff66b63333ULL, 0x91633ff2c65c6363ULL,
+	0x0802100a04120202ULL, 0x92aa39384993aaaaULL, 0xd971afa8e2de7171ULL,
+	0x07c80ecf8dc6c8c8ULL, 0x6419c87d32d11919ULL, 0x39497270923b4949ULL,
+	0x43d9869aaf5fd9d9ULL, 0xeff2c31df931f2f2ULL, 0xabe34b48dba8e3e3ULL,
+	0x715be22ab6b95b5bULL, 0x1a8834920dbc8888ULL, 0x529aa4c8293e9a9aULL,
+	0x98262dbe4c0b2626ULL, 0xc8328dfa64bf3232ULL, 0xfab0e94a7d59b0b0ULL,
+	0x83e91b6acff2e9e9ULL, 0x3c0f78331e770f0fULL, 0x73d5e6a6b733d5d5ULL,
+	0x3a8074ba1df48080ULL, 0xc2be997c6127bebeULL, 0x13cd26de87ebcdcdULL,
+	0xd034bde468893434ULL, 0x3d487a7590324848ULL, 0xdbffab24e354ffffULL,
+	0xf57af78ff48d7a7aULL, 0x7a90f4ea3d649090ULL, 0x615fc23ebe9d5f5fULL,
+	0x80201da0403d2020ULL, 0xbd6867d5d00f6868ULL, 0x681ad07234ca1a1aULL,
+	0x82ae192c41b7aeaeULL, 0xeab4c95e757db4b4ULL, 0x4d549a19a8ce5454ULL,
+	0x7693ece53b7f9393ULL, 0x88220daa442f2222ULL, 0x8d6407e9c8636464ULL,
+	0xe3f1db12ff2af1f1ULL, 0xd173bfa2e6cc7373ULL, 0x4812905a24821212ULL,
+	0x1d403a5d807a4040ULL, 0x2008402810480808ULL, 0x2bc356e89b95c3c3ULL,
+	0x97ec337bc5dfececULL, 0x4bdb9690ab4ddbdbULL, 0xbea1611f5fc0a1a1ULL,
+	0x0e8d1c8307918d8dULL, 0xf43df5c97ac83d3dULL, 0x6697ccf1335b9797ULL,
+	0x0000000000000000ULL, 0x1bcf36d483f9cfcfULL, 0xac2b4587566e2b2bULL,
+	0xc57697b3ece17676ULL, 0x328264b019e68282ULL, 0x7fd6fea9b128d6d6ULL,
+	0x6c1bd87736c31b1bULL, 0xeeb5c15b7774b5b5ULL, 0x86af112943beafafULL,
+	0xb56a77dfd41d6a6aULL, 0x5d50ba0da0ea5050ULL, 0x0945124c8a574545ULL,
+	0xebf3cb18fb38f3f3ULL, 0xc0309df060ad3030ULL, 0x9bef2b74c3c4efefULL,
+	0xfc3fe5c37eda3f3fULL, 0x4955921caac75555ULL, 0xb2a2791059dba2a2ULL,
+	0x8fea0365c9e9eaeaULL, 0x89650fecca6a6565ULL, 0xd2bab9686903babaULL,
+	0xbc2f65935e4a2f2fULL, 0x27c04ee79d8ec0c0ULL, 0x5fdebe81a160dedeULL,
+	0x701ce06c38fc1c1cULL, 0xd3fdbb2ee746fdfdULL, 0x294d52649a1f4d4dULL,
+	0x7292e4e039769292ULL, 0xc9758fbceafa7575ULL, 0x1806301e0c360606ULL,
+	0x128a249809ae8a8aULL, 0xf2b2f940794bb2b2ULL, 0xbfe66359d185e6e6ULL,
+	0x380e70361c7e0e0eULL, 0x7c1ff8633ee71f1fULL, 0x956237f7c4556262ULL,
+	0x77d4eea3b53ad4d4ULL, 0x9aa829324d81a8a8ULL, 0x6296c4f431529696ULL,
+	0xc3f99b3aef62f9f9ULL, 0x33c566f697a3c5c5ULL, 0x942535b14a102525ULL,
+	0x7959f220b2ab5959ULL, 0x2a8454ae15d08484ULL, 0xd572b7a7e4c57272ULL,
+	0xe439d5dd72ec3939ULL, 0x2d4c5a6198164c4cULL, 0x655eca3bbc945e5eULL,
+	0xfd78e785f09f7878ULL, 0xe038ddd870e53838ULL, 0x0a8c148605988c8cULL,
+	0x63d1c6b2bf17d1d1ULL, 0xaea5410b57e4a5a5ULL, 0xafe2434dd9a1e2e2ULL,
+	0x99612ff8c24e6161ULL, 0xf6b3f1457b42b3b3ULL, 0x842115a542342121ULL,
+	0x4a9c94d625089c9cULL, 0x781ef0663cee1e1eULL, 0x1143225286614343ULL,
+	0x3bc776fc93b1c7c7ULL, 0xd7fcb32be54ffcfcULL, 0x1004201408240404ULL,
+	0x5951b208a2e35151ULL, 0x5e99bcc72f259999ULL, 0xa96d4fc4da226d6dULL,
+	0x340d68391a650d0dULL, 0xcffa8335e979fafaULL, 0x5bdfb684a369dfdfULL,
+	0xe57ed79bfca97e7eULL, 0x90243db448192424ULL, 0xec3bc5d776fe3b3bULL,
+	0x96ab313d4b9aababULL, 0x1fce3ed181f0ceceULL, 0x4411885522991111ULL,
+	0x068f0c8903838f8fULL, 0x254e4a6b9c044e4eULL, 0xe6b7d1517366b7b7ULL,
+	0x8beb0b60cbe0ebebULL, 0xf03cfdcc78c13c3cULL, 0x3e817cbf1ffd8181ULL,
+	0x6a94d4fe35409494ULL, 0xfbf7eb0cf31cf7f7ULL, 0xdeb9a1676f18b9b9ULL,
+	0x4c13985f268b1313ULL, 0xb02c7d9c58512c2cULL, 0x6bd3d6b8bb05d3d3ULL,
+	0xbbe76b5cd38ce7e7ULL, 0xa56e57cbdc396e6eULL, 0x37c46ef395aac4c4ULL,
+	0x0c03180f061b0303ULL, 0x45568a13acdc5656ULL, 0x0d441a49885e4444ULL,
+	0xe17fdf9efea07f7fULL, 0x9ea921374f88a9a9ULL, 0xa82a4d8254672a2aULL,
+	0xd6bbb16d6b0abbbbULL, 0x23c146e29f87c1c1ULL, 0x5153a202a6f15353ULL,
+	0x57dcae8ba572dcdcULL, 0x2c0b582716530b0bULL, 0x4e9d9cd327019d9dULL,
+	0xad6c47c1d82b6c6cULL, 0xc43195f562a43131ULL, 0xcd7487b9e8f37474ULL,
+	0xfff6e309f115f6f6ULL, 0x05460a438c4c4646ULL, 0x8aac092645a5acacULL,
+	0x1e893c970fb58989ULL, 0x5014a04428b41414ULL, 0xa3e15b42dfbae1e1ULL,
+	0x5816b04e2ca61616ULL, 0xe83acdd274f73a3aULL, 0xb9696fd0d2066969ULL,
+	0x2409482d12410909ULL, 0xdd70a7ade0d77070ULL, 0xe2b6d954716fb6b6ULL,
+	0x67d0ceb7bd1ed0d0ULL, 0x93ed3b7ec7d6ededULL, 0x17cc2edb85e2ccccULL,
+	0x15422a5784684242ULL, 0x5a98b4c22d2c9898ULL, 0xaaa4490e55eda4a4ULL,
+	0xa0285d8850752828ULL, 0x6d5cda31b8865c5cULL, 0xc7f8933fed6bf8f8ULL,
+	0x228644a411c28686ULL,
+};
+
+static const u64 C7[256] = {
+	0x186018c07830d818ULL, 0x238c2305af462623ULL, 0xc63fc67ef991b8c6ULL,
+	0xe887e8136fcdfbe8ULL, 0x8726874ca113cb87ULL, 0xb8dab8a9626d11b8ULL,
+	0x0104010805020901ULL, 0x4f214f426e9e0d4fULL, 0x36d836adee6c9b36ULL,
+	0xa6a2a6590451ffa6ULL, 0xd26fd2debdb90cd2ULL, 0xf5f3f5fb06f70ef5ULL,
+	0x79f979ef80f29679ULL, 0x6fa16f5fcede306fULL, 0x917e91fcef3f6d91ULL,
+	0x525552aa07a4f852ULL, 0x609d6027fdc04760ULL, 0xbccabc89766535bcULL,
+	0x9b569baccd2b379bULL, 0x8e028e048c018a8eULL, 0xa3b6a371155bd2a3ULL,
+	0x0c300c603c186c0cULL, 0x7bf17bff8af6847bULL, 0x35d435b5e16a8035ULL,
+	0x1d741de8693af51dULL, 0xe0a7e05347ddb3e0ULL, 0xd77bd7f6acb321d7ULL,
+	0xc22fc25eed999cc2ULL, 0x2eb82e6d965c432eULL, 0x4b314b627a96294bULL,
+	0xfedffea321e15dfeULL, 0x5741578216aed557ULL, 0x155415a8412abd15ULL,
+	0x77c1779fb6eee877ULL, 0x37dc37a5eb6e9237ULL, 0xe5b3e57b56d79ee5ULL,
+	0x9f469f8cd923139fULL, 0xf0e7f0d317fd23f0ULL, 0x4a354a6a7f94204aULL,
+	0xda4fda9e95a944daULL, 0x587d58fa25b0a258ULL, 0xc903c906ca8fcfc9ULL,
+	0x29a429558d527c29ULL, 0x0a280a5022145a0aULL, 0xb1feb1e14f7f50b1ULL,
+	0xa0baa0691a5dc9a0ULL, 0x6bb16b7fdad6146bULL, 0x852e855cab17d985ULL,
+	0xbdcebd8173673cbdULL, 0x5d695dd234ba8f5dULL, 0x1040108050209010ULL,
+	0xf4f7f4f303f507f4ULL, 0xcb0bcb16c08bddcbULL, 0x3ef83eedc67cd33eULL,
+	0x05140528110a2d05ULL, 0x6781671fe6ce7867ULL, 0xe4b7e47353d597e4ULL,
+	0x279c2725bb4e0227ULL, 0x4119413258827341ULL, 0x8b168b2c9d0ba78bULL,
+	0xa7a6a7510153f6a7ULL, 0x7de97dcf94fab27dULL, 0x956e95dcfb374995ULL,
+	0xd847d88e9fad56d8ULL, 0xfbcbfb8b30eb70fbULL, 0xee9fee2371c1cdeeULL,
+	0x7ced7cc791f8bb7cULL, 0x66856617e3cc7166ULL, 0xdd53dda68ea77bddULL,
+	0x175c17b84b2eaf17ULL, 0x47014702468e4547ULL, 0x9e429e84dc211a9eULL,
+	0xca0fca1ec589d4caULL, 0x2db42d75995a582dULL, 0xbfc6bf9179632ebfULL,
+	0x071c07381b0e3f07ULL, 0xad8ead012347acadULL, 0x5a755aea2fb4b05aULL,
+	0x8336836cb51bef83ULL, 0x33cc3385ff66b633ULL, 0x6391633ff2c65c63ULL,
+	0x020802100a041202ULL, 0xaa92aa39384993aaULL, 0x71d971afa8e2de71ULL,
+	0xc807c80ecf8dc6c8ULL, 0x196419c87d32d119ULL, 0x4939497270923b49ULL,
+	0xd943d9869aaf5fd9ULL, 0xf2eff2c31df931f2ULL, 0xe3abe34b48dba8e3ULL,
+	0x5b715be22ab6b95bULL, 0x881a8834920dbc88ULL, 0x9a529aa4c8293e9aULL,
+	0x2698262dbe4c0b26ULL, 0x32c8328dfa64bf32ULL, 0xb0fab0e94a7d59b0ULL,
+	0xe983e91b6acff2e9ULL, 0x0f3c0f78331e770fULL, 0xd573d5e6a6b733d5ULL,
+	0x803a8074ba1df480ULL, 0xbec2be997c6127beULL, 0xcd13cd26de87ebcdULL,
+	0x34d034bde4688934ULL, 0x483d487a75903248ULL, 0xffdbffab24e354ffULL,
+	0x7af57af78ff48d7aULL, 0x907a90f4ea3d6490ULL, 0x5f615fc23ebe9d5fULL,
+	0x2080201da0403d20ULL, 0x68bd6867d5d00f68ULL, 0x1a681ad07234ca1aULL,
+	0xae82ae192c41b7aeULL, 0xb4eab4c95e757db4ULL, 0x544d549a19a8ce54ULL,
+	0x937693ece53b7f93ULL, 0x2288220daa442f22ULL, 0x648d6407e9c86364ULL,
+	0xf1e3f1db12ff2af1ULL, 0x73d173bfa2e6cc73ULL, 0x124812905a248212ULL,
+	0x401d403a5d807a40ULL, 0x0820084028104808ULL, 0xc32bc356e89b95c3ULL,
+	0xec97ec337bc5dfecULL, 0xdb4bdb9690ab4ddbULL, 0xa1bea1611f5fc0a1ULL,
+	0x8d0e8d1c8307918dULL, 0x3df43df5c97ac83dULL, 0x976697ccf1335b97ULL,
+	0x0000000000000000ULL, 0xcf1bcf36d483f9cfULL, 0x2bac2b4587566e2bULL,
+	0x76c57697b3ece176ULL, 0x82328264b019e682ULL, 0xd67fd6fea9b128d6ULL,
+	0x1b6c1bd87736c31bULL, 0xb5eeb5c15b7774b5ULL, 0xaf86af112943beafULL,
+	0x6ab56a77dfd41d6aULL, 0x505d50ba0da0ea50ULL, 0x450945124c8a5745ULL,
+	0xf3ebf3cb18fb38f3ULL, 0x30c0309df060ad30ULL, 0xef9bef2b74c3c4efULL,
+	0x3ffc3fe5c37eda3fULL, 0x554955921caac755ULL, 0xa2b2a2791059dba2ULL,
+	0xea8fea0365c9e9eaULL, 0x6589650fecca6a65ULL, 0xbad2bab9686903baULL,
+	0x2fbc2f65935e4a2fULL, 0xc027c04ee79d8ec0ULL, 0xde5fdebe81a160deULL,
+	0x1c701ce06c38fc1cULL, 0xfdd3fdbb2ee746fdULL, 0x4d294d52649a1f4dULL,
+	0x927292e4e0397692ULL, 0x75c9758fbceafa75ULL, 0x061806301e0c3606ULL,
+	0x8a128a249809ae8aULL, 0xb2f2b2f940794bb2ULL, 0xe6bfe66359d185e6ULL,
+	0x0e380e70361c7e0eULL, 0x1f7c1ff8633ee71fULL, 0x62956237f7c45562ULL,
+	0xd477d4eea3b53ad4ULL, 0xa89aa829324d81a8ULL, 0x966296c4f4315296ULL,
+	0xf9c3f99b3aef62f9ULL, 0xc533c566f697a3c5ULL, 0x25942535b14a1025ULL,
+	0x597959f220b2ab59ULL, 0x842a8454ae15d084ULL, 0x72d572b7a7e4c572ULL,
+	0x39e439d5dd72ec39ULL, 0x4c2d4c5a6198164cULL, 0x5e655eca3bbc945eULL,
+	0x78fd78e785f09f78ULL, 0x38e038ddd870e538ULL, 0x8c0a8c148605988cULL,
+	0xd163d1c6b2bf17d1ULL, 0xa5aea5410b57e4a5ULL, 0xe2afe2434dd9a1e2ULL,
+	0x6199612ff8c24e61ULL, 0xb3f6b3f1457b42b3ULL, 0x21842115a5423421ULL,
+	0x9c4a9c94d625089cULL, 0x1e781ef0663cee1eULL, 0x4311432252866143ULL,
+	0xc73bc776fc93b1c7ULL, 0xfcd7fcb32be54ffcULL, 0x0410042014082404ULL,
+	0x515951b208a2e351ULL, 0x995e99bcc72f2599ULL, 0x6da96d4fc4da226dULL,
+	0x0d340d68391a650dULL, 0xfacffa8335e979faULL, 0xdf5bdfb684a369dfULL,
+	0x7ee57ed79bfca97eULL, 0x2490243db4481924ULL, 0x3bec3bc5d776fe3bULL,
+	0xab96ab313d4b9aabULL, 0xce1fce3ed181f0ceULL, 0x1144118855229911ULL,
+	0x8f068f0c8903838fULL, 0x4e254e4a6b9c044eULL, 0xb7e6b7d1517366b7ULL,
+	0xeb8beb0b60cbe0ebULL, 0x3cf03cfdcc78c13cULL, 0x813e817cbf1ffd81ULL,
+	0x946a94d4fe354094ULL, 0xf7fbf7eb0cf31cf7ULL, 0xb9deb9a1676f18b9ULL,
+	0x134c13985f268b13ULL, 0x2cb02c7d9c58512cULL, 0xd36bd3d6b8bb05d3ULL,
+	0xe7bbe76b5cd38ce7ULL, 0x6ea56e57cbdc396eULL, 0xc437c46ef395aac4ULL,
+	0x030c03180f061b03ULL, 0x5645568a13acdc56ULL, 0x440d441a49885e44ULL,
+	0x7fe17fdf9efea07fULL, 0xa99ea921374f88a9ULL, 0x2aa82a4d8254672aULL,
+	0xbbd6bbb16d6b0abbULL, 0xc123c146e29f87c1ULL, 0x535153a202a6f153ULL,
+	0xdc57dcae8ba572dcULL, 0x0b2c0b582716530bULL, 0x9d4e9d9cd327019dULL,
+	0x6cad6c47c1d82b6cULL, 0x31c43195f562a431ULL, 0x74cd7487b9e8f374ULL,
+	0xf6fff6e309f115f6ULL, 0x4605460a438c4c46ULL, 0xac8aac092645a5acULL,
+	0x891e893c970fb589ULL, 0x145014a04428b414ULL, 0xe1a3e15b42dfbae1ULL,
+	0x165816b04e2ca616ULL, 0x3ae83acdd274f73aULL, 0x69b9696fd0d20669ULL,
+	0x092409482d124109ULL, 0x70dd70a7ade0d770ULL, 0xb6e2b6d954716fb6ULL,
+	0xd067d0ceb7bd1ed0ULL, 0xed93ed3b7ec7d6edULL, 0xcc17cc2edb85e2ccULL,
+	0x4215422a57846842ULL, 0x985a98b4c22d2c98ULL, 0xa4aaa4490e55eda4ULL,
+	0x28a0285d88507528ULL, 0x5c6d5cda31b8865cULL, 0xf8c7f8933fed6bf8ULL,
+	0x86228644a411c286ULL,
+};
+
+static const u64 rc[WHIRLPOOL_ROUNDS + 1] = {
+	0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL,
+	0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL,
+	0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL,
+	0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL,
+};
+
+/**
+ * The core Whirlpool transform.
+ */
+
+static void whirlpool_process_buffer(struct whirlpool_ctx *wctx) {
+	int i, r;
+	u64 K[8];        /* the round key */
+	u64 block[8];    /* mu(buffer) */
+	u64 state[8];    /* the cipher state */
+	u64 L[8];
+	u8 *buffer = wctx->buffer;
+
+	for (i = 0; i < 8; i++, buffer += 8) {
+		block[i] =
+		(((u64)buffer[0]        ) << 56) ^
+		(((u64)buffer[1] & 0xffL) << 48) ^
+		(((u64)buffer[2] & 0xffL) << 40) ^
+		(((u64)buffer[3] & 0xffL) << 32) ^
+		(((u64)buffer[4] & 0xffL) << 24) ^
+		(((u64)buffer[5] & 0xffL) << 16) ^
+		(((u64)buffer[6] & 0xffL) <<  8) ^
+		(((u64)buffer[7] & 0xffL)      );
+	}
+
+	state[0] = block[0] ^ (K[0] = wctx->hash[0]);
+	state[1] = block[1] ^ (K[1] = wctx->hash[1]);
+	state[2] = block[2] ^ (K[2] = wctx->hash[2]);
+	state[3] = block[3] ^ (K[3] = wctx->hash[3]);
+	state[4] = block[4] ^ (K[4] = wctx->hash[4]);
+	state[5] = block[5] ^ (K[5] = wctx->hash[5]);
+	state[6] = block[6] ^ (K[6] = wctx->hash[6]);
+	state[7] = block[7] ^ (K[7] = wctx->hash[7]);
+
+	for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) {
+
+		L[0] = C0[(int)(K[0] >> 56)       ] ^
+			   C1[(int)(K[7] >> 48) & 0xff] ^
+			   C2[(int)(K[6] >> 40) & 0xff] ^
+			   C3[(int)(K[5] >> 32) & 0xff] ^
+			   C4[(int)(K[4] >> 24) & 0xff] ^
+			   C5[(int)(K[3] >> 16) & 0xff] ^
+			   C6[(int)(K[2] >>  8) & 0xff] ^
+			   C7[(int)(K[1]      ) & 0xff] ^
+			   rc[r];
+
+		L[1] = C0[(int)(K[1] >> 56)       ] ^
+			   C1[(int)(K[0] >> 48) & 0xff] ^
+			   C2[(int)(K[7] >> 40) & 0xff] ^
+			   C3[(int)(K[6] >> 32) & 0xff] ^
+			   C4[(int)(K[5] >> 24) & 0xff] ^
+			   C5[(int)(K[4] >> 16) & 0xff] ^
+			   C6[(int)(K[3] >>  8) & 0xff] ^
+			   C7[(int)(K[2]      ) & 0xff];
+
+		L[2] = C0[(int)(K[2] >> 56)       ] ^
+			   C1[(int)(K[1] >> 48) & 0xff] ^
+			   C2[(int)(K[0] >> 40) & 0xff] ^
+			   C3[(int)(K[7] >> 32) & 0xff] ^
+			   C4[(int)(K[6] >> 24) & 0xff] ^
+			   C5[(int)(K[5] >> 16) & 0xff] ^
+			   C6[(int)(K[4] >>  8) & 0xff] ^
+			   C7[(int)(K[3]      ) & 0xff];
+
+		L[3] = C0[(int)(K[3] >> 56)       ] ^
+			   C1[(int)(K[2] >> 48) & 0xff] ^
+			   C2[(int)(K[1] >> 40) & 0xff] ^
+			   C3[(int)(K[0] >> 32) & 0xff] ^
+			   C4[(int)(K[7] >> 24) & 0xff] ^
+			   C5[(int)(K[6] >> 16) & 0xff] ^
+			   C6[(int)(K[5] >>  8) & 0xff] ^
+			   C7[(int)(K[4]      ) & 0xff];
+
+		L[4] = C0[(int)(K[4] >> 56)       ] ^
+			   C1[(int)(K[3] >> 48) & 0xff] ^
+			   C2[(int)(K[2] >> 40) & 0xff] ^
+			   C3[(int)(K[1] >> 32) & 0xff] ^
+			   C4[(int)(K[0] >> 24) & 0xff] ^
+			   C5[(int)(K[7] >> 16) & 0xff] ^
+			   C6[(int)(K[6] >>  8) & 0xff] ^
+			   C7[(int)(K[5]      ) & 0xff];
+
+		L[5] = C0[(int)(K[5] >> 56)       ] ^
+			   C1[(int)(K[4] >> 48) & 0xff] ^
+			   C2[(int)(K[3] >> 40) & 0xff] ^
+			   C3[(int)(K[2] >> 32) & 0xff] ^
+			   C4[(int)(K[1] >> 24) & 0xff] ^
+			   C5[(int)(K[0] >> 16) & 0xff] ^
+			   C6[(int)(K[7] >>  8) & 0xff] ^
+			   C7[(int)(K[6]      ) & 0xff];
+
+		L[6] = C0[(int)(K[6] >> 56)       ] ^
+			   C1[(int)(K[5] >> 48) & 0xff] ^
+			   C2[(int)(K[4] >> 40) & 0xff] ^
+			   C3[(int)(K[3] >> 32) & 0xff] ^
+			   C4[(int)(K[2] >> 24) & 0xff] ^
+			   C5[(int)(K[1] >> 16) & 0xff] ^
+			   C6[(int)(K[0] >>  8) & 0xff] ^
+			   C7[(int)(K[7]      ) & 0xff];
+
+		L[7] = C0[(int)(K[7] >> 56)       ] ^
+			   C1[(int)(K[6] >> 48) & 0xff] ^
+			   C2[(int)(K[5] >> 40) & 0xff] ^
+			   C3[(int)(K[4] >> 32) & 0xff] ^
+			   C4[(int)(K[3] >> 24) & 0xff] ^
+			   C5[(int)(K[2] >> 16) & 0xff] ^
+			   C6[(int)(K[1] >>  8) & 0xff] ^
+			   C7[(int)(K[0]      ) & 0xff];
+
+		K[0] = L[0];
+		K[1] = L[1];
+		K[2] = L[2];
+		K[3] = L[3];
+		K[4] = L[4];
+		K[5] = L[5];
+		K[6] = L[6];
+		K[7] = L[7];
+
+		L[0] = C0[(int)(state[0] >> 56)       ] ^
+			   C1[(int)(state[7] >> 48) & 0xff] ^
+			   C2[(int)(state[6] >> 40) & 0xff] ^
+			   C3[(int)(state[5] >> 32) & 0xff] ^
+			   C4[(int)(state[4] >> 24) & 0xff] ^
+			   C5[(int)(state[3] >> 16) & 0xff] ^
+			   C6[(int)(state[2] >>  8) & 0xff] ^
+			   C7[(int)(state[1]      ) & 0xff] ^
+			   K[0];
+
+		L[1] = C0[(int)(state[1] >> 56)       ] ^
+			   C1[(int)(state[0] >> 48) & 0xff] ^
+			   C2[(int)(state[7] >> 40) & 0xff] ^
+			   C3[(int)(state[6] >> 32) & 0xff] ^
+			   C4[(int)(state[5] >> 24) & 0xff] ^
+			   C5[(int)(state[4] >> 16) & 0xff] ^
+			   C6[(int)(state[3] >>  8) & 0xff] ^
+			   C7[(int)(state[2]      ) & 0xff] ^
+			   K[1];
+
+		L[2] = C0[(int)(state[2] >> 56)       ] ^
+			   C1[(int)(state[1] >> 48) & 0xff] ^
+			   C2[(int)(state[0] >> 40) & 0xff] ^
+			   C3[(int)(state[7] >> 32) & 0xff] ^
+			   C4[(int)(state[6] >> 24) & 0xff] ^
+			   C5[(int)(state[5] >> 16) & 0xff] ^
+			   C6[(int)(state[4] >>  8) & 0xff] ^
+			   C7[(int)(state[3]      ) & 0xff] ^
+			   K[2];
+
+		L[3] = C0[(int)(state[3] >> 56)       ] ^
+			   C1[(int)(state[2] >> 48) & 0xff] ^
+			   C2[(int)(state[1] >> 40) & 0xff] ^
+			   C3[(int)(state[0] >> 32) & 0xff] ^
+			   C4[(int)(state[7] >> 24) & 0xff] ^
+			   C5[(int)(state[6] >> 16) & 0xff] ^
+			   C6[(int)(state[5] >>  8) & 0xff] ^
+			   C7[(int)(state[4]      ) & 0xff] ^
+			   K[3];
+
+		L[4] = C0[(int)(state[4] >> 56)       ] ^
+			   C1[(int)(state[3] >> 48) & 0xff] ^
+			   C2[(int)(state[2] >> 40) & 0xff] ^
+			   C3[(int)(state[1] >> 32) & 0xff] ^
+			   C4[(int)(state[0] >> 24) & 0xff] ^
+			   C5[(int)(state[7] >> 16) & 0xff] ^
+			   C6[(int)(state[6] >>  8) & 0xff] ^
+			   C7[(int)(state[5]      ) & 0xff] ^
+			   K[4];
+
+		L[5] = C0[(int)(state[5] >> 56)       ] ^
+			   C1[(int)(state[4] >> 48) & 0xff] ^
+			   C2[(int)(state[3] >> 40) & 0xff] ^
+			   C3[(int)(state[2] >> 32) & 0xff] ^
+			   C4[(int)(state[1] >> 24) & 0xff] ^
+			   C5[(int)(state[0] >> 16) & 0xff] ^
+			   C6[(int)(state[7] >>  8) & 0xff] ^
+			   C7[(int)(state[6]      ) & 0xff] ^
+			   K[5];
+
+		L[6] = C0[(int)(state[6] >> 56)       ] ^
+			   C1[(int)(state[5] >> 48) & 0xff] ^
+			   C2[(int)(state[4] >> 40) & 0xff] ^
+			   C3[(int)(state[3] >> 32) & 0xff] ^
+			   C4[(int)(state[2] >> 24) & 0xff] ^
+			   C5[(int)(state[1] >> 16) & 0xff] ^
+			   C6[(int)(state[0] >>  8) & 0xff] ^
+			   C7[(int)(state[7]      ) & 0xff] ^
+			   K[6];
+
+		L[7] = C0[(int)(state[7] >> 56)       ] ^
+			   C1[(int)(state[6] >> 48) & 0xff] ^
+			   C2[(int)(state[5] >> 40) & 0xff] ^
+			   C3[(int)(state[4] >> 32) & 0xff] ^
+			   C4[(int)(state[3] >> 24) & 0xff] ^
+			   C5[(int)(state[2] >> 16) & 0xff] ^
+			   C6[(int)(state[1] >>  8) & 0xff] ^
+			   C7[(int)(state[0]      ) & 0xff] ^
+			   K[7];
+
+		state[0] = L[0];
+		state[1] = L[1];
+		state[2] = L[2];
+		state[3] = L[3];
+		state[4] = L[4];
+		state[5] = L[5];
+		state[6] = L[6];
+		state[7] = L[7];
+	}
+	/*
+	* apply the Miyaguchi-Preneel compression function:
+	*/
+	wctx->hash[0] ^= state[0] ^ block[0];
+	wctx->hash[1] ^= state[1] ^ block[1];
+	wctx->hash[2] ^= state[2] ^ block[2];
+	wctx->hash[3] ^= state[3] ^ block[3];
+	wctx->hash[4] ^= state[4] ^ block[4];
+	wctx->hash[5] ^= state[5] ^ block[5];
+	wctx->hash[6] ^= state[6] ^ block[6];
+	wctx->hash[7] ^= state[7] ^ block[7];
+
+}
+
+static void whirlpool_init (void *ctx) {
+	int i;
+	struct whirlpool_ctx *wctx = ctx;
+
+	memset(wctx->bitLength, 0, 32);
+	wctx->bufferBits = wctx->bufferPos = 0;
+	wctx->buffer[0] = 0;
+	for (i = 0; i < 8; i++) {
+		wctx->hash[i] = 0L;
+	}
+}
+
+static void whirlpool_update(void *ctx, const u8 *source, unsigned int len)
+{
+
+	struct whirlpool_ctx *wctx = ctx;
+	int sourcePos    = 0;
+	unsigned int bits_len = len * 8; // convert to number of bits
+	int sourceGap    = (8 - ((int)bits_len & 7)) & 7;
+	int bufferRem    = wctx->bufferBits & 7;
+	int i;
+	u32 b, carry;
+	u8 *buffer       = wctx->buffer;
+	u8 *bitLength    = wctx->bitLength;
+	int bufferBits   = wctx->bufferBits;
+	int bufferPos    = wctx->bufferPos;
+
+	u64 value = bits_len;
+	for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) {
+		carry += bitLength[i] + ((u32)value & 0xff);
+		bitLength[i] = (u8)carry;
+		carry >>= 8;
+		value >>= 8;
+	}
+	while (bits_len > 8) {
+		b = ((source[sourcePos] << sourceGap) & 0xff) |
+		((source[sourcePos + 1] & 0xff) >> (8 - sourceGap));
+		buffer[bufferPos++] |= (u8)(b >> bufferRem);
+		bufferBits += 8 - bufferRem;
+		if (bufferBits == WHIRLPOOL_DIGEST_SIZE * 8) {
+			whirlpool_process_buffer(wctx);
+			bufferBits = bufferPos = 0;
+		}
+		buffer[bufferPos] = b << (8 - bufferRem);
+		bufferBits += bufferRem;
+		bits_len -= 8;
+		sourcePos++;
+	}
+	if (bits_len > 0) {
+		b = (source[sourcePos] << sourceGap) & 0xff;
+		buffer[bufferPos] |= b >> bufferRem;
+	} else {
+		b = 0;
+	}
+	if (bufferRem + bits_len < 8) {
+		bufferBits += bits_len;
+	} else {
+		bufferPos++;
+		bufferBits += 8 - bufferRem;
+		bits_len -= 8 - bufferRem;
+		if (bufferBits == WHIRLPOOL_DIGEST_SIZE * 8) {
+			whirlpool_process_buffer(wctx);
+			bufferBits = bufferPos = 0;
+		}
+		buffer[bufferPos] = b << (8 - bufferRem);
+		bufferBits += (int)bits_len;
+	}
+
+	wctx->bufferBits   = bufferBits;
+	wctx->bufferPos    = bufferPos;
+
+}
+
+static void whirlpool_final(void *ctx, u8 *out)
+{
+	struct whirlpool_ctx *wctx = ctx;
+	int i;
+   	u8 *buffer      = wctx->buffer;
+   	u8 *bitLength   = wctx->bitLength;
+   	int bufferBits  = wctx->bufferBits;
+   	int bufferPos   = wctx->bufferPos;
+   	u8 *digest      = out;
+
+   	buffer[bufferPos] |= 0x80U >> (bufferBits & 7);
+   	bufferPos++;
+   	if (bufferPos > WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) {
+   		if (bufferPos < WHIRLPOOL_BLOCK_SIZE) {
+	   	memset(&buffer[bufferPos], 0, WHIRLPOOL_BLOCK_SIZE - bufferPos);
+   		}
+   		whirlpool_process_buffer(wctx);
+   		bufferPos = 0;
+   	}
+   	if (bufferPos < WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) {
+   		memset(&buffer[bufferPos], 0,
+			  (WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) - bufferPos);
+   	}
+   	bufferPos = WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES;
+   	memcpy(&buffer[WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES],
+		   bitLength, WHIRLPOOL_LENGTHBYTES);
+   	whirlpool_process_buffer(wctx);
+   	for (i = 0; i < WHIRLPOOL_DIGEST_SIZE/8; i++) {
+		digest[0] = (u8)(wctx->hash[i] >> 56);
+		digest[1] = (u8)(wctx->hash[i] >> 48);
+		digest[2] = (u8)(wctx->hash[i] >> 40);
+		digest[3] = (u8)(wctx->hash[i] >> 32);
+		digest[4] = (u8)(wctx->hash[i] >> 24);
+		digest[5] = (u8)(wctx->hash[i] >> 16);
+		digest[6] = (u8)(wctx->hash[i] >>  8);
+		digest[7] = (u8)(wctx->hash[i]      );
+		digest += 8;
+   	}
+   	wctx->bufferBits   = bufferBits;
+   	wctx->bufferPos    = bufferPos;
+}
+
+static struct crypto_alg alg = {
+	.cra_name	=	"whirlpool",
+	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	=	WHIRLPOOL_BLOCK_SIZE,
+	.cra_ctxsize	=	sizeof(struct whirlpool_ctx),
+	.cra_module	=	THIS_MODULE,
+	.cra_list       =       LIST_HEAD_INIT(alg.cra_list),	
+	.cra_u		=	{ .digest = {
+	.dia_digestsize	=	WHIRLPOOL_DIGEST_SIZE,
+	.dia_init   	= 	whirlpool_init,
+	.dia_update 	=	whirlpool_update,
+	.dia_final  	=	whirlpool_final } }
+};
+
+static int __init init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Whirlpool Message Digest Algorithm");
diff -Nru a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
--- a/drivers/atm/idt77252.c	2004-07-12 01:01:05 -07:00
+++ b/drivers/atm/idt77252.c	2004-08-24 02:08:33 -07:00
@@ -3681,18 +3681,25 @@
 	struct idt77252_dev *card;
 	struct atm_dev *dev;
 	ushort revision = 0;
-	int i;
+	int i, err;
 
 
+	if (pci_enable_device(pcidev)) {
+		printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev));
+		return -ENODEV;
+	}
+
 	if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) {
 		printk("idt77252-%d: can't read PCI_REVISION_ID\n", index);
-		return -ENODEV;
+		err = -ENODEV;
+		goto err_out_disable_pdev;
 	}
 
 	card = kmalloc(sizeof(struct idt77252_dev), GFP_KERNEL);
 	if (!card) {
 		printk("idt77252-%d: can't allocate private data\n", index);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_out_disable_pdev;
 	}
 	memset(card, 0, sizeof(struct idt77252_dev));
 
@@ -3718,23 +3725,21 @@
 	card->membase = (unsigned long) ioremap(membase, 1024);
 	if (!card->membase) {
 		printk("%s: can't ioremap() membase\n", card->name);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_free_card;
 	}
 
 	if (idt77252_preset(card)) {
 		printk("%s: preset failed\n", card->name);
-		iounmap((void *) card->membase);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_iounmap;
 	}
 
 	dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL);
 	if (!dev) {
 		printk("%s: can't register atm device\n", card->name);
-		iounmap((void *) card->membase);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_iounmap;
 	}
 	dev->dev_data = card;
 	card->atmdev = dev;
@@ -3743,9 +3748,8 @@
 	suni_init(dev);
 	if (!dev->phy) {
 		printk("%s: can't init SUNI\n", card->name);
-		deinit_card(card);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_deinit_card;
 	}
 #endif	/* CONFIG_ATM_IDT77252_USE_SUNI */
 
@@ -3756,9 +3760,8 @@
 			    ioremap(srambase | 0x200000 | (i << 18), 4);
 		if (!card->fbq[i]) {
 			printk("%s: can't ioremap() FBQ%d\n", card->name, i);
-			deinit_card(card);
-			kfree(card);
-			return -EIO;
+			err = -EIO;
+			goto err_out_deinit_card;
 		}
 	}
 
@@ -3769,9 +3772,8 @@
 
 	if (init_card(dev)) {
 		printk("%s: init_card failed\n", card->name);
-		deinit_card(card);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_deinit_card;
 	}
 
 	dev->ci_range.vpi_bits = card->vpibits;
@@ -3783,12 +3785,8 @@
 
 	if (idt77252_dev_open(card)) {
 		printk("%s: dev_open failed\n", card->name);
-
-		if (dev->phy->stop)
-			dev->phy->stop(dev);
-		deinit_card(card);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_stop;
 	}
 
 	*last = card;
@@ -3796,6 +3794,23 @@
 	index++;
 
 	return 0;
+
+err_out_stop:
+	if (dev->phy->stop)
+		dev->phy->stop(dev);
+
+err_out_deinit_card:
+	deinit_card(card);
+
+err_out_iounmap:
+	iounmap((void *) card->membase);
+
+err_out_free_card:
+	kfree(card);
+
+err_out_disable_pdev:
+	pci_disable_device(pcidev);
+	return err;
 }
 
 static struct pci_device_id idt77252_pci_tbl[] =
@@ -3848,6 +3863,7 @@
 		if (dev->phy->stop)
 			dev->phy->stop(dev);
 		deinit_card(card);
+		pci_disable_device(card->pcidev);
 		kfree(card);
 	}
 
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	2004-06-10 02:35:56 -07:00
+++ b/drivers/base/class.c	2004-08-07 03:27:32 -07:00
@@ -349,13 +349,18 @@
 
 int class_device_add(struct class_device *class_dev)
 {
-	struct class * parent;
+	struct class * parent = NULL;
 	struct class_interface * class_intf;
 	int error;
 
 	class_dev = class_device_get(class_dev);
-	if (!class_dev || !strlen(class_dev->class_id))
+	if (!class_dev)
 		return -EINVAL;
+
+	if (!strlen(class_dev->class_id)) {
+		error = -EINVAL;
+		goto register_done;
+	}
 
 	parent = class_get(class_dev->class);
 
diff -Nru a/drivers/base/node.c b/drivers/base/node.c
--- a/drivers/base/node.c	2004-06-27 00:19:31 -07:00
+++ b/drivers/base/node.c	2004-08-24 02:09:05 -07:00
@@ -19,7 +19,7 @@
 static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
 {
 	struct node *node_dev = to_node(dev);
-	cpumask_t mask = node_dev->cpumap;
+	cpumask_t mask = node_to_cpumask(node_dev->sysdev.id);
 	int len;
 
 	/* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */
@@ -38,11 +38,19 @@
 	int n;
 	int nid = dev->id;
 	struct sysinfo i;
+	unsigned long inactive;
+	unsigned long active;
+	unsigned long free;
+
 	si_meminfo_node(&i, nid);
+	__get_zone_counts(&active, &inactive, &free, NODE_DATA(nid));
+
 	n = sprintf(buf, "\n"
 		       "Node %d MemTotal:     %8lu kB\n"
 		       "Node %d MemFree:      %8lu kB\n"
 		       "Node %d MemUsed:      %8lu kB\n"
+		       "Node %d Active:       %8lu kB\n"
+		       "Node %d Inactive:     %8lu kB\n"
 		       "Node %d HighTotal:    %8lu kB\n"
 		       "Node %d HighFree:     %8lu kB\n"
 		       "Node %d LowTotal:     %8lu kB\n"
@@ -50,6 +58,8 @@
 		       nid, K(i.totalram),
 		       nid, K(i.freeram),
 		       nid, K(i.totalram - i.freeram),
+		       nid, K(active),
+		       nid, K(inactive),
 		       nid, K(i.totalhigh),
 		       nid, K(i.freehigh),
 		       nid, K(i.totalram - i.totalhigh),
@@ -111,7 +121,6 @@
 {
 	int error;
 
-	node->cpumap = node_to_cpumask(num);
 	node->sysdev.id = num;
 	node->sysdev.cls = &node_class;
 	error = sysdev_register(&node->sysdev);
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	2004-08-23 01:14:48 -07:00
+++ b/drivers/block/ll_rw_blk.c	2004-08-26 23:31:38 -07:00
@@ -2535,6 +2535,7 @@
 	sector_t maxsector;
 	int ret, nr_sectors = bio_sectors(bio);
 
+	might_sleep();
 	/* Test device or partition size, when known. */
 	maxsector = bio->bi_bdev->bd_inode->i_size >> 9;
 	if (maxsector) {
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	2004-06-12 20:52:29 -07:00
+++ b/drivers/block/rd.c	2004-08-24 11:41:17 -07:00
@@ -349,13 +349,17 @@
 	if (rd_bdev[unit] == NULL) {
 		struct block_device *bdev = inode->i_bdev;
 		struct address_space *mapping;
+		unsigned bsize;
 		int gfp_mask;
 
 		inode = igrab(bdev->bd_inode);
 		rd_bdev[unit] = bdev;
 		bdev->bd_openers++;
-		bdev->bd_block_size = rd_blocksize;
-		inode->i_size = get_capacity(rd_disks[unit])<<9;
+		bsize = bdev_hardsect_size(bdev);
+		bdev->bd_block_size = bsize;
+		inode->i_blkbits = blksize_bits(bsize);
+		inode->i_size = get_capacity(bdev->bd_disk)<<9;
+
 		mapping = inode->i_mapping;
 		mapping->a_ops = &ramdisk_aops;
 		mapping->backing_dev_info = &rd_backing_dev_info;
@@ -449,6 +453,7 @@
 			goto out_queue;
 
 		blk_queue_make_request(rd_queue[i], &rd_make_request);
+		blk_queue_hardsect_size(rd_queue[i], rd_blocksize);
 
 		/* rd_size is given in kB */
 		disk->major = RAMDISK_MAJOR;
diff -Nru a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
--- a/drivers/block/scsi_ioctl.c	2004-08-23 08:18:56 -07:00
+++ b/drivers/block/scsi_ioctl.c	2004-08-27 08:36:38 -07:00
@@ -178,6 +178,7 @@
 		safe_for_write(GPCMD_SEND_EVENT),
 		safe_for_write(GPCMD_SEND_KEY),
 		safe_for_write(GPCMD_SEND_OPC),
+		safe_for_write(GPCMD_SEND_CUE_SHEET),
 		safe_for_write(GPCMD_SET_SPEED),
 		safe_for_write(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL),
 		safe_for_write(GPCMD_LOAD_UNLOAD),
@@ -537,6 +538,7 @@
 		 * old junk scsi send command ioctl
 		 */
 		case SCSI_IOCTL_SEND_COMMAND:
+			printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
 			err = -EINVAL;
 			if (!arg)
 				break;
diff -Nru a/drivers/block/ub.c b/drivers/block/ub.c
--- a/drivers/block/ub.c	2004-08-12 15:02:32 -07:00
+++ b/drivers/block/ub.c	2004-08-23 17:02:30 -07:00
@@ -107,6 +107,8 @@
  * A second ought to be enough for a 32K transfer (UB_MAX_SECTORS)
  * even if a webcam hogs the bus (famous last words).
  * Some CDs need a second to spin up though.
+ * ZIP drive rejects commands when it's not spinning,
+ * so it does not need long timeouts either.
  */
 #define UB_URB_TIMEOUT	(HZ*2)
 #define UB_CTRL_TIMEOUT	(HZ/2) /* 500ms ought to be enough to clear a stall */
@@ -287,6 +289,7 @@
 
 	struct ub_completion work_done;
 	struct urb work_urb;
+	struct timer_list work_timer;
 	int last_pipe;			/* What might need clearing */
 	struct bulk_cb_wrap work_bcb;
 	struct bulk_cs_wrap work_bcs;
@@ -776,16 +779,20 @@
 	sc->last_pipe = sc->send_bulk_pipe;
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
 	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
-	sc->work_urb.timeout = UB_URB_TIMEOUT;
+	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
 
 	/* Fill what we shouldn't be filling, because usb-storage did so. */
 	sc->work_urb.actual_length = 0;
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
+	sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+	add_timer(&sc->work_timer);
+
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
 		printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */
+		del_timer(&sc->work_timer);
 		ub_complete(&sc->work_done);
 		return rc;
 	}
@@ -796,6 +803,19 @@
 }
 
 /*
+ * Timeout handler.
+ */
+static void ub_urb_timeout(unsigned long arg)
+{
+	struct ub_dev *sc = (struct ub_dev *) arg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sc->lock, flags);
+	usb_unlink_urb(&sc->work_urb);
+	spin_unlock_irqrestore(&sc->lock, flags);
+}
+
+/*
  * Completion routine for the work URB.
  *
  * This can be called directly from usb_submit_urb (while we have
@@ -943,14 +963,18 @@
 		sc->last_pipe = pipe;
 		usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
 		    cmd->data, cmd->len, ub_urb_complete, sc);
-		sc->work_urb.timeout = UB_URB_TIMEOUT;
+		sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
 		sc->work_urb.actual_length = 0;
 		sc->work_urb.error_count = 0;
 		sc->work_urb.status = 0;
 
+		sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+		add_timer(&sc->work_timer);
+
 		if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 			/* XXX Clear stalls */
 			printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
+			del_timer(&sc->work_timer);
 			ub_complete(&sc->work_done);
 			ub_state_done(sc, cmd, rc);
 			return;
@@ -1034,16 +1058,20 @@
 			usb_fill_bulk_urb(&sc->work_urb, sc->dev,
 			    sc->recv_bulk_pipe, &sc->work_bcs,
 			    US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
-			sc->work_urb.timeout = UB_URB_TIMEOUT;
+			sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
 			sc->work_urb.actual_length = 0;
 			sc->work_urb.error_count = 0;
 			sc->work_urb.status = 0;
 
+			sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+			add_timer(&sc->work_timer);
+
 			rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC);
 			if (rc != 0) {
 				/* XXX Clear stalls */
 				printk("%s: CSW #%d submit failed (%d)\n",
 				   sc->name, cmd->tag, rc); /* P3 */
+				del_timer(&sc->work_timer);
 				ub_complete(&sc->work_done);
 				ub_state_done(sc, cmd, rc);
 				return;
@@ -1153,14 +1181,18 @@
 	sc->last_pipe = sc->recv_bulk_pipe;
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
 	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
-	sc->work_urb.timeout = UB_URB_TIMEOUT;
+	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
 	sc->work_urb.actual_length = 0;
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
+	sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+	add_timer(&sc->work_timer);
+
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
 		printk("ub: CSW #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
+		del_timer(&sc->work_timer);
 		ub_complete(&sc->work_done);
 		ub_state_done(sc, cmd, rc);
 		return;
@@ -1233,14 +1265,17 @@
 	UB_INIT_COMPLETION(sc->work_done);
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
-	    (unsigned char*) cr, NULL, 0,
-	    ub_urb_complete, sc);
-	sc->work_urb.timeout = UB_CTRL_TIMEOUT;
+	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
+	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
 	sc->work_urb.actual_length = 0;
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
+	sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT;
+	add_timer(&sc->work_timer);
+
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+		del_timer(&sc->work_timer);
 		ub_complete(&sc->work_done);
 		return rc;
 	}
@@ -1653,6 +1688,12 @@
 	complete(cop);
 }
 
+static void ub_probe_timeout(unsigned long arg)
+{
+	struct completion *cop = (struct completion *) arg;
+	complete(cop);
+}
+
 /*
  * Clear initial stalls.
  */
@@ -1661,6 +1702,7 @@
 	int endp;
 	struct usb_ctrlrequest *cr;
 	struct completion compl;
+	struct timer_list timer;
 	int rc;
 
 	init_completion(&compl);
@@ -1677,21 +1719,35 @@
 	cr->wLength = cpu_to_le16(0);
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
-	    (unsigned char*) cr, NULL, 0,
-	    ub_probe_urb_complete, &compl);
-	sc->work_urb.timeout = UB_CTRL_TIMEOUT;
+	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
+	sc->work_urb.transfer_flags = 0;
 	sc->work_urb.actual_length = 0;
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
+	init_timer(&timer);
+	timer.function = ub_probe_timeout;
+	timer.data = (unsigned long) &compl;
+	timer.expires = jiffies + UB_CTRL_TIMEOUT;
+	add_timer(&timer);
+
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
 		printk(KERN_WARNING
 		     "%s: Unable to submit a probe clear (%d)\n", sc->name, rc);
+		del_timer_sync(&timer);
 		return rc;
 	}
 
 	wait_for_completion(&compl);
 
+	del_timer_sync(&timer);
+	/*
+	 * Most of the time, URB was done and dev set to NULL, and so
+	 * the unlink bounces out with ENODEV. We do not call usb_kill_urb
+	 * because we still think about a backport to 2.4.
+	 */
+	usb_unlink_urb(&sc->work_urb);
+
 	/* reset the endpoint toggle */
 	usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0);
 
@@ -1766,6 +1822,10 @@
 	usb_init_urb(&sc->work_urb);
 	tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
 	atomic_set(&sc->poison, 0);
+
+	init_timer(&sc->work_timer);
+	sc->work_timer.data = (unsigned long) sc;
+	sc->work_timer.function = ub_urb_timeout;
 
 	ub_init_completion(&sc->work_done);
 	sc->work_done.done = 1;		/* A little yuk, but oh well... */
diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig
--- a/drivers/char/Kconfig	2004-08-23 01:15:10 -07:00
+++ b/drivers/char/Kconfig	2004-08-28 10:04:06 -07:00
@@ -595,39 +595,6 @@
 	  which will also be compiled when this driver is built as a
 	  module.
 
-config QIC02_TAPE
-	tristate "QIC-02 tape support"
-	help
-	  If you have a non-SCSI tape drive like that, say Y.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called tpqic02.
-
-config QIC02_DYNCONF
-	bool "Do you want runtime configuration for QIC-02"
-	depends on QIC02_TAPE
-	help
-	  You can either configure this driver once and for all by editing a
-	  header file (<file:include/linux/tpqic02.h>), in which case you
-	  should say N, or you can fetch a program via anonymous FTP which is
-	  able to configure this driver during runtime.  The program to do
-	  this is called 'qic02conf' and it is part of the
-	  tpqic02-support-X.Y.tar.gz support package.
-
-	  If you want to use the qic02conf program, say Y.
-
-comment "Edit configuration parameters in ./include/linux/tpqic02.h!"
-	depends on QIC02_TAPE && !QIC02_DYNCONF
-
-comment "Setting runtime QIC-02 configuration is done with qic02conf"
-	depends on QIC02_TAPE && QIC02_DYNCONF
-
-comment "from the tpqic02-support package.  It is available at"
-	depends on QIC02_TAPE && QIC02_DYNCONF
-
-comment "metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/"
-	depends on QIC02_TAPE && QIC02_DYNCONF
-
 source "drivers/char/ipmi/Kconfig"
 
 source "drivers/char/watchdog/Kconfig"
@@ -786,7 +753,7 @@
 
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
-	depends on RTC!=y && !IA64
+	depends on RTC!=y && !IA64 && !ARM
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	2004-08-23 01:15:10 -07:00
+++ b/drivers/char/Makefile	2004-08-24 02:08:49 -07:00
@@ -7,8 +7,11 @@
 #
 FONTMAPFILE = cp437.uni
 
-obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o
+obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
 
+obj-$(CONFIG_LEGACY_PTYS)	+= pty.o
+obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
+obj-y				+= misc.o
 obj-$(CONFIG_VT)		+= vt_ioctl.o vc_screen.o consolemap.o \
 				   consolemap_deftbl.o selection.o keyboard.o
 obj-$(CONFIG_HW_CONSOLE)	+= vt.o defkeymap.o
diff -Nru a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
--- a/drivers/char/agp/Kconfig	2004-08-09 17:57:15 -07:00
+++ b/drivers/char/agp/Kconfig	2004-08-27 13:05:05 -07:00
@@ -1,5 +1,5 @@
 config AGP
-	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU && !M68K
+	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU && !M68K && !ARM
 	default y if GART_IOMMU
 	---help---
 	  AGP (Accelerated Graphics Port) is a bus system mainly used to
diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c
--- a/drivers/char/amiserial.c	2004-02-22 19:09:24 -08:00
+++ b/drivers/char/amiserial.c	2004-08-24 02:08:52 -07:00
@@ -430,7 +430,7 @@
 
 	if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
 #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-		printk("ttyS%02d CD now %s...", info->line,
+		printk("ttyS%d CD now %s...", info->line,
 		       (!(status & SER_DCD)) ? "on" : "off");
 #endif
 		if (!(status & SER_DCD))
@@ -2095,7 +2095,7 @@
 	  continue;
 	*/
 
-	printk(KERN_INFO "ttyS%02d is the amiga builtin serial port\n",
+	printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
 		       state->line);
 
 	/* Hardware set up */
diff -Nru a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
--- a/drivers/char/drm/Kconfig	2004-07-05 04:19:34 -07:00
+++ b/drivers/char/drm/Kconfig	2004-08-27 02:38:14 -07:00
@@ -62,7 +62,18 @@
 	  Choose this option if you have a system that has Intel 830M, 845G,
 	  852GM, 855GM or 865G integrated graphics.  If M is selected, the
 	  module will be called i830.  AGP support is required for this driver
-	  to work.
+	  to work. This driver will eventually be replaced by the i915 one.
+
+config DRM_I915
+	tristate "Intel 830M, 845G, 852GM, 855GM, 865G, 915G"
+	depends on DRM && AGP && AGP_INTEL
+	help
+	  Choose this option if you have a system that has Intel 830M, 845G,
+	  852GM, 855GM 865G or 915G integrated graphics.  If M is selected, the
+	  module will be called i915.  AGP support is required for this driver
+	  to work. This driver will eventually replace the I830 driver, when
+	  later release of X start to use the new DDX and DRI.
+	
 
 config DRM_MGA
 	tristate "Matrox g200/g400"
diff -Nru a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
--- a/drivers/char/drm/Makefile	2003-07-23 10:48:09 -07:00
+++ b/drivers/char/drm/Makefile	2004-08-27 02:38:14 -07:00
@@ -8,6 +8,7 @@
 mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
 i810-objs   := i810_drv.o i810_dma.o
 i830-objs   := i830_drv.o i830_dma.o i830_irq.o
+i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
 radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
 ffb-objs    := ffb_drv.o ffb_context.o
 sis-objs    := sis_drv.o sis_ds.o sis_mm.o
@@ -19,6 +20,7 @@
 obj-$(CONFIG_DRM_MGA)	+= mga.o
 obj-$(CONFIG_DRM_I810)	+= i810.o
 obj-$(CONFIG_DRM_I830)	+= i830.o
+obj-$(CONFIG_DRM_I915)  += i915.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
 obj-$(CONFIG_DRM_SIS)   += sis.o
 
diff -Nru a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h
--- a/drivers/char/drm/drm_bufs.h	2004-07-16 07:14:58 -07:00
+++ b/drivers/char/drm/drm_bufs.h	2004-08-27 17:02:28 -07:00
@@ -691,6 +691,7 @@
 			buf->used    = 0;
 			buf->offset  = (dma->byte_count + byte_count + offset);
 			buf->address = (void *)(page + offset);
+			buf->bus_address = virt_to_bus(buf->address);
 			buf->next    = NULL;
 			buf->waiting = 0;
 			buf->pending = 0;
diff -Nru a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
--- a/drivers/char/drm/drm_os_linux.h	2004-04-09 22:34:47 -07:00
+++ b/drivers/char/drm/drm_os_linux.h	2004-08-27 02:38:14 -07:00
@@ -17,10 +17,14 @@
 #define DRM_UDELAY(d)			udelay(d)
 /** Read a byte from a MMIO region */
 #define DRM_READ8(map, offset)		readb(((unsigned long)(map)->handle) + (offset))
+/** Read a word from a MMIO region */
+#define DRM_READ16(map, offset)         readw(((unsigned long)(map)->handle) + (offset))
 /** Read a dword from a MMIO region */
 #define DRM_READ32(map, offset)		readl(((unsigned long)(map)->handle) + (offset))
 /** Write a byte into a MMIO region */
 #define DRM_WRITE8(map, offset, val)	writeb(val, ((unsigned long)(map)->handle) + (offset))
+/** Write a word into a MMIO region */
+#define DRM_WRITE16(map, offset, val)   writew(val, ((unsigned long)(map)->handle) + (offset))
 /** Write a dword into a MMIO region */
 #define DRM_WRITE32(map, offset, val)	writel(val, ((unsigned long)(map)->handle) + (offset))
 /** Read memory barrier */
diff -Nru a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
--- a/drivers/char/drm/drm_pciids.h	2004-04-25 23:44:34 -07:00
+++ b/drivers/char/drm/drm_pciids.h	2004-08-27 02:38:14 -07:00
@@ -201,3 +201,11 @@
 #define ffb_PCI_IDS \
 	{0, 0, 0}
 
+#define i915_PCI_IDS \
+	{0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0, 0, 0}
+
diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
--- a/drivers/char/drm/i810_dma.c	2004-07-16 07:14:58 -07:00
+++ b/drivers/char/drm/i810_dma.c	2004-08-27 11:26:15 -07:00
@@ -844,13 +844,10 @@
 	if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
 		unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
 
-		put_user((GFX_OP_PRIMITIVE | prim |
-					     ((used/4)-2)),
-		(u32 __user *)buf_priv->virtual);
+		*(u32 *)buf_priv->kernel_virtual = ((GFX_OP_PRIMITIVE | prim | ((used/4)-2)));
 
 		if (used & 4) {
-			put_user(0,
-			(u32 __user *)((u32)buf_priv->virtual + used));
+			*(u32 *)((u32)buf_priv->kernel_virtual + used) = 0;
 			used += 4;
 		}
 
diff -Nru a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
--- a/drivers/char/drm/i830_dma.c	2004-07-16 07:14:58 -07:00
+++ b/drivers/char/drm/i830_dma.c	2004-08-27 11:26:17 -07:00
@@ -1166,19 +1166,19 @@
    	DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
 
 	if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
-		u32  __user *vp = buf_priv->virtual;
+		u32 *vp = buf_priv->kernel_virtual;
 
-		put_user( (GFX_OP_PRIMITIVE |
-			 sarea_priv->vertex_prim |
-			  ((used/4)-2)), &vp[0]);
+		vp[0] = (GFX_OP_PRIMITIVE |
+			sarea_priv->vertex_prim |
+			((used/4)-2));
 
 		if (dev_priv->use_mi_batchbuffer_start) {
-			put_user(MI_BATCH_BUFFER_END, &vp[used/4]);
+			vp[used/4] = MI_BATCH_BUFFER_END;
 			used += 4; 
 		}
 		
 		if (used & 4) {
-			put_user(0, &vp[used/4]);
+			vp[used/4] = 0;
 			used += 4;
 		}
 
diff -Nru a/drivers/char/drm/i915.h b/drivers/char/drm/i915.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/drm/i915.h	2004-08-27 02:33:29 -07:00
@@ -0,0 +1,88 @@
+/* i915.h -- Intel I915 DRM template customization -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef __I915_H__
+#define __I915_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) i915_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP		1
+#define __MUST_HAVE_AGP		1
+#define __HAVE_MTRR		1
+#define __HAVE_CTX_BITMAP	1
+
+#define DRIVER_AUTHOR		"Tungsten Graphics, Inc."
+
+#define DRIVER_NAME		"i915"
+#define DRIVER_DESC		"Intel Graphics"
+#define DRIVER_DATE		"20040405"
+
+/* Interface history:
+ *
+ * 1.1: Original.
+ */
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		1
+#define DRIVER_PATCHLEVEL	0
+
+#define DRIVER_IOCTLS							    \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_INIT)]   = { i915_dma_init,    1, 1 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_FLUSH)]  = { i915_flush_ioctl, 1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_FLIP)]   = { i915_flip_bufs,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_BATCHBUFFER)] = { i915_batchbuffer, 1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_IRQ_EMIT)] = { i915_irq_emit,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_IRQ_WAIT)] = { i915_irq_wait,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_GETPARAM)] = { i915_getparam,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_SETPARAM)] = { i915_setparam,  1, 1 }, \
+        [DRM_IOCTL_NR(DRM_IOCTL_I915_ALLOC)]   = { i915_mem_alloc,  1, 0 }, \
+        [DRM_IOCTL_NR(DRM_IOCTL_I915_FREE)]    = { i915_mem_free,    1, 0 }, \
+        [DRM_IOCTL_NR(DRM_IOCTL_I915_INIT_HEAP)] = { i915_mem_init_heap, 1, 1 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I915_CMDBUFFER)] = { i915_cmdbuffer, 1, 0 }
+
+#define __HAVE_COUNTERS         4
+#define __HAVE_COUNTER6         _DRM_STAT_IRQ
+#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
+#define __HAVE_COUNTER9         _DRM_STAT_DMA
+
+/* Driver customization:
+ */
+#define DRIVER_PRETAKEDOWN() do {					\
+	if ( dev->dev_private ) {					\
+		drm_i915_private_t *dev_priv = dev->dev_private;	\
+	        i915_mem_takedown( &(dev_priv->agp_heap) );             \
+ 	}								\
+	i915_dma_cleanup( dev );					\
+} while (0)
+
+/* When a client dies:
+ *    - Free any alloced agp memory.
+ */
+#define DRIVER_PRERELEASE() 						\
+do {									\
+	if ( dev->dev_private ) {					\
+		drm_i915_private_t *dev_priv = dev->dev_private;	\
+                i915_mem_release( dev, filp, dev_priv->agp_heap );	\
+	}								\
+} while (0)
+
+/* We use our own dma mechanisms, not the drm template code.  However,
+ * the shared IRQ code is useful to us:
+ */
+#define __HAVE_DMA		0
+#define __HAVE_IRQ		1
+#define __HAVE_SHARED_IRQ	1
+
+#define __HAVE_PM		1
+
+#endif
diff -Nru a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/drm/i915_dma.c	2004-08-27 17:05:27 -07:00
@@ -0,0 +1,714 @@
+/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "i915.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static inline void i915_print_status_page(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 *temp = dev_priv->hw_status_page;
+
+	if (!temp) {
+		DRM_DEBUG("no status page\n");
+		return;
+	}
+
+	DRM_DEBUG("hw_status: Interrupt Status : %x\n", temp[0]);
+	DRM_DEBUG("hw_status: LpRing Head ptr : %x\n", temp[1]);
+	DRM_DEBUG("hw_status: IRing Head ptr : %x\n", temp[2]);
+	DRM_DEBUG("hw_status: Reserved : %x\n", temp[3]);
+	DRM_DEBUG("hw_status: Driver Counter : %d\n", temp[5]);
+
+}
+
+/* Really want an OS-independent resettable timer.  Would like to have
+ * this loop run for (eg) 3 sec, but have the timer reset every time
+ * the head pointer changes, so that EBUSY only happens if the ring
+ * actually stalls for (eg) 3 seconds.
+ */
+int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+	u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	int i;
+
+	for (i = 0; i < 10000; i++) {
+		ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+		ring->space = ring->head - (ring->tail + 8);
+		if (ring->space < 0)
+			ring->space += ring->Size;
+		if (ring->space >= n)
+			return 0;
+
+		dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+
+		if (ring->head != last_head)
+			i = 0;
+
+		last_head = ring->head;
+	}
+
+	return DRM_ERR(EBUSY);
+}
+
+void i915_kernel_lost_context(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+
+	ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+	ring->space = ring->head - (ring->tail + 8);
+	if (ring->space < 0)
+		ring->space += ring->Size;
+
+	if (ring->head == ring->tail)
+		dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
+}
+
+int i915_dma_cleanup(drm_device_t * dev)
+{
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if (dev->irq)
+		DRM(irq_uninstall) (dev);
+
+	if (dev->dev_private) {
+		drm_i915_private_t *dev_priv =
+		    (drm_i915_private_t *) dev->dev_private;
+
+		if (dev_priv->ring.virtual_start) {
+			DRM_IOREMAPFREE(&dev_priv->ring.map, dev);
+		}
+
+		if (dev_priv->hw_status_page) {
+			pci_free_consistent(dev->pdev, PAGE_SIZE,
+					    dev_priv->hw_status_page,
+					    dev_priv->dma_status_page);
+			/* Need to rewrite hardware status page */
+			I915_WRITE(0x02080, 0x1ffff000);
+		}
+
+		DRM(free) (dev->dev_private, sizeof(drm_i915_private_t),
+			   DRM_MEM_DRIVER);
+
+		dev->dev_private = NULL;
+	}
+
+	return 0;
+}
+
+static int i915_initialize(drm_device_t * dev,
+			   drm_i915_private_t * dev_priv,
+			   drm_i915_init_t * init)
+{
+	memset(dev_priv, 0, sizeof(drm_i915_private_t));
+
+	DRM_GETSAREA();
+	if (!dev_priv->sarea) {
+		DRM_ERROR("can not find sarea!\n");
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_FIND_MAP(dev_priv->mmio_map, init->mmio_offset);
+	if (!dev_priv->mmio_map) {
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		DRM_ERROR("can not find mmio map!\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->sarea_priv = (drm_i915_sarea_t *)
+	    ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
+
+	dev_priv->ring.Start = init->ring_start;
+	dev_priv->ring.End = init->ring_end;
+	dev_priv->ring.Size = init->ring_size;
+	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+	dev_priv->ring.map.offset = init->ring_start;
+	dev_priv->ring.map.size = init->ring_size;
+	dev_priv->ring.map.type = 0;
+	dev_priv->ring.map.flags = 0;
+	dev_priv->ring.map.mtrr = 0;
+
+	DRM_IOREMAP(&dev_priv->ring.map, dev);
+
+	if (dev_priv->ring.map.handle == NULL) {
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		DRM_ERROR("can not ioremap virtual address for"
+			  " ring buffer\n");
+		return DRM_ERR(ENOMEM);
+	}
+
+	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+	dev_priv->back_offset = init->back_offset;
+	dev_priv->front_offset = init->front_offset;
+	dev_priv->current_page = 0;
+	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+
+	/* We are using separate values as placeholders for mechanisms for
+	 * private backbuffer/depthbuffer usage.
+	 */
+	dev_priv->use_mi_batchbuffer_start = 0;
+
+	/* Allow hardware batchbuffers unless told otherwise.
+	 */
+	dev_priv->allow_batchbuffer = 1;
+
+	/* Program Hardware Status Page */
+	dev_priv->hw_status_page =
+	    pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+				 &dev_priv->dma_status_page);
+
+	if (!dev_priv->hw_status_page) {
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		DRM_ERROR("Can not allocate hardware status page\n");
+		return DRM_ERR(ENOMEM);
+	}
+	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+	I915_WRITE(0x02080, dev_priv->dma_status_page);
+	DRM_DEBUG("Enabled hardware status page\n");
+
+	dev->dev_private = (void *)dev_priv;
+
+	return 0;
+}
+
+static int i915_resume(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	if (!dev_priv->sarea) {
+		DRM_ERROR("can not find sarea!\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (!dev_priv->mmio_map) {
+		DRM_ERROR("can not find mmio map!\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (dev_priv->ring.map.handle == NULL) {
+		DRM_ERROR("can not ioremap virtual address for"
+			  " ring buffer\n");
+		return DRM_ERR(ENOMEM);
+	}
+
+	/* Program Hardware Status Page */
+	if (!dev_priv->hw_status_page) {
+		DRM_ERROR("Can not find hardware status page\n");
+		return DRM_ERR(EINVAL);
+	}
+	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+	I915_WRITE(0x02080, dev_priv->dma_status_page);
+	DRM_DEBUG("Enabled hardware status page\n");
+
+	return 0;
+}
+
+int i915_dma_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv;
+	drm_i915_init_t init;
+	int retcode = 0;
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data,
+				 sizeof(init));
+
+	switch (init.func) {
+	case I915_INIT_DMA:
+		dev_priv = DRM(alloc) (sizeof(drm_i915_private_t),
+				       DRM_MEM_DRIVER);
+		if (dev_priv == NULL)
+			return DRM_ERR(ENOMEM);
+		retcode = i915_initialize(dev, dev_priv, &init);
+		break;
+	case I915_CLEANUP_DMA:
+		retcode = i915_dma_cleanup(dev);
+		break;
+	case I915_RESUME_DMA:
+		retcode = i915_resume(dev);
+		break;
+	default:
+		retcode = -EINVAL;
+		break;
+	}
+
+	return retcode;
+}
+
+/* Implement basically the same security restrictions as hardware does
+ * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
+ *
+ * Most of the calculations below involve calculating the size of a
+ * particular instruction.  It's important to get the size right as
+ * that tells us where the next instruction to check is.  Any illegal
+ * instruction detected will be given a size of zero, which is a
+ * signal to abort the rest of the buffer.
+ */
+static int do_validate_cmd(int cmd)
+{
+	switch (((cmd >> 29) & 0x7)) {
+	case 0x0:
+		switch ((cmd >> 23) & 0x3f) {
+		case 0x0:
+			return 1;	/* MI_NOOP */
+		case 0x4:
+			return 1;	/* MI_FLUSH */
+		default:
+			return 0;	/* disallow everything else */
+		}
+		break;
+	case 0x1:
+		return 0;	/* reserved */
+	case 0x2:
+		return (cmd & 0xff) + 2;	/* 2d commands */
+	case 0x3:
+		if (((cmd >> 24) & 0x1f) <= 0x18)
+			return 1;
+
+		switch ((cmd >> 24) & 0x1f) {
+		case 0x1c:
+			return 1;
+		case 0x1d:
+			return (cmd & 0xffff) + 2;
+		case 0x1e:
+			if (cmd & (1 << 23))
+				return (cmd & 0xffff) + 1;
+			else
+				return 1;
+		case 0x1f:
+			if ((cmd & (1 << 23)) == 0)	/* inline vertices */
+				return (cmd & 0x1ffff) + 2;
+			else if (cmd & (1 << 17))	/* indirect random */
+				if ((cmd & 0xffff) == 0)
+					return 0;	/* unknown length, too hard */
+				else
+					return (((cmd & 0xffff) + 1) / 2) + 1;
+			else
+				return 2;	/* indirect sequential */
+		default:
+			return 0;
+		}
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int validate_cmd(int cmd)
+{
+	int ret = do_validate_cmd(cmd);
+
+/* 	printk("validate_cmd( %x ): %d\n", cmd, ret); */
+
+	return ret;
+}
+
+static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int i;
+	RING_LOCALS;
+
+	for (i = 0; i < dwords;) {
+		int cmd, sz;
+
+		if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
+			return DRM_ERR(EINVAL);
+
+/* 		printk("%d/%d ", i, dwords); */
+
+		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
+			return DRM_ERR(EINVAL);
+
+		BEGIN_LP_RING(sz);
+		OUT_RING(cmd);
+
+		while (++i, --sz) {
+			if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
+							 sizeof(cmd))) {
+				return DRM_ERR(EINVAL);
+			}
+			OUT_RING(cmd);
+		}
+		ADVANCE_LP_RING();
+	}
+
+	return 0;
+}
+
+static int i915_emit_box(drm_device_t * dev,
+			 drm_clip_rect_t __user * boxes,
+			 int i, int DR1, int DR4)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_clip_rect_t box;
+	RING_LOCALS;
+
+	if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
+		return EFAULT;
+	}
+
+	if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
+		DRM_ERROR("Bad box %d,%d..%d,%d\n",
+			  box.x1, box.y1, box.x2, box.y2);
+		return DRM_ERR(EINVAL);
+	}
+
+	BEGIN_LP_RING(6);
+	OUT_RING(GFX_OP_DRAWRECT_INFO);
+	OUT_RING(DR1);
+	OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+	OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+	OUT_RING(DR4);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	return 0;
+}
+
+static int i915_dispatch_cmdbuffer(drm_device_t * dev,
+				   drm_i915_cmdbuffer_t * cmd)
+{
+	int nbox = cmd->num_cliprects;
+	int i = 0, count, ret;
+
+	if (cmd->sz & 0x3) {
+		DRM_ERROR("alignment");
+		return DRM_ERR(EINVAL);
+	}
+
+	i915_kernel_lost_context(dev);
+
+	count = nbox ? nbox : 1;
+
+	for (i = 0; i < count; i++) {
+		if (i < nbox) {
+			ret = i915_emit_box(dev, cmd->cliprects, i,
+					    cmd->DR1, cmd->DR4);
+			if (ret)
+				return ret;
+		}
+
+		ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int i915_dispatch_batchbuffer(drm_device_t * dev,
+				     drm_i915_batchbuffer_t * batch)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_clip_rect_t __user *boxes = batch->cliprects;
+	int nbox = batch->num_cliprects;
+	int i = 0, count;
+	RING_LOCALS;
+
+	if ((batch->start | batch->used) & 0x7) {
+		DRM_ERROR("alignment");
+		return DRM_ERR(EINVAL);
+	}
+
+	i915_kernel_lost_context(dev);
+
+	count = nbox ? nbox : 1;
+
+	for (i = 0; i < count; i++) {
+		if (i < nbox) {
+			int ret = i915_emit_box(dev, boxes, i,
+						batch->DR1, batch->DR4);
+			if (ret)
+				return ret;
+		}
+
+		if (dev_priv->use_mi_batchbuffer_start) {
+			BEGIN_LP_RING(2);
+			OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+			ADVANCE_LP_RING();
+		} else {
+			BEGIN_LP_RING(4);
+			OUT_RING(MI_BATCH_BUFFER);
+			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+			OUT_RING(batch->start + batch->used - 4);
+			OUT_RING(0);
+			ADVANCE_LP_RING();
+		}
+	}
+
+	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+
+	BEGIN_LP_RING(4);
+	OUT_RING(CMD_STORE_DWORD_IDX);
+	OUT_RING(20);
+	OUT_RING(dev_priv->counter);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	return 0;
+}
+
+static int i915_dispatch_flip(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+		  __FUNCTION__,
+		  dev_priv->current_page,
+		  dev_priv->sarea_priv->pf_current_page);
+
+	i915_kernel_lost_context(dev);
+
+	BEGIN_LP_RING(2);
+	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	BEGIN_LP_RING(6);
+	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
+	OUT_RING(0);
+	if (dev_priv->current_page == 0) {
+		OUT_RING(dev_priv->back_offset);
+		dev_priv->current_page = 1;
+	} else {
+		OUT_RING(dev_priv->front_offset);
+		dev_priv->current_page = 0;
+	}
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	BEGIN_LP_RING(2);
+	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+
+	BEGIN_LP_RING(4);
+	OUT_RING(CMD_STORE_DWORD_IDX);
+	OUT_RING(20);
+	OUT_RING(dev_priv->counter);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+	return 0;
+}
+
+static int i915_quiescent(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	i915_kernel_lost_context(dev);
+	return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+}
+
+int i915_flush_ioctl(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+
+	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("i915_flush_ioctl called without lock held\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	return i915_quiescent(dev);
+}
+
+int i915_batchbuffer(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 *hw_status = dev_priv->hw_status_page;
+	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+	    dev_priv->sarea_priv;
+	drm_i915_batchbuffer_t batch;
+	int ret;
+
+	if (!dev_priv->allow_batchbuffer) {
+		DRM_ERROR("Batchbuffer ioctl disabled\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data,
+				 sizeof(batch));
+
+	DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
+		  batch.start, batch.used, batch.num_cliprects);
+
+	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("i915_batchbuffer called without lock held\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
+						       batch.num_cliprects *
+						       sizeof(drm_clip_rect_t)))
+		return DRM_ERR(EFAULT);
+
+	ret = i915_dispatch_batchbuffer(dev, &batch);
+
+	sarea_priv->last_dispatch = (int)hw_status[5];
+	return ret;
+}
+
+int i915_cmdbuffer(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 *hw_status = dev_priv->hw_status_page;
+	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+	    dev_priv->sarea_priv;
+	drm_i915_cmdbuffer_t cmdbuf;
+	int ret;
+
+	DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data,
+				 sizeof(cmdbuf));
+
+	DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
+		  cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
+
+	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("i915_cmdbuffer called without lock held\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (cmdbuf.num_cliprects &&
+	    DRM_VERIFYAREA_READ(cmdbuf.cliprects,
+				cmdbuf.num_cliprects *
+				sizeof(drm_clip_rect_t))) {
+		DRM_ERROR("Fault accessing cliprects\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
+	if (ret) {
+		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
+		return ret;
+	}
+
+	sarea_priv->last_dispatch = (int)hw_status[5];
+	return 0;
+}
+
+int i915_do_cleanup_pageflip(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+	if (dev_priv->current_page != 0)
+		i915_dispatch_flip(dev);
+
+	return 0;
+}
+
+int i915_flip_bufs(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("i915_flip_buf called without lock held\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	return i915_dispatch_flip(dev);
+}
+
+int i915_getparam(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_getparam_t param;
+	int value;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data,
+				 sizeof(param));
+
+	switch (param.param) {
+	case I915_PARAM_IRQ_ACTIVE:
+		value = dev->irq ? 1 : 0;
+		break;
+	case I915_PARAM_ALLOW_BATCHBUFFER:
+		value = dev_priv->allow_batchbuffer ? 1 : 0;
+		break;
+	default:
+		DRM_ERROR("Unkown parameter %d\n", param.param);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+		DRM_ERROR("DRM_COPY_TO_USER failed\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+int i915_setparam(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_setparam_t param;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data,
+				 sizeof(param));
+
+	switch (param.param) {
+	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
+		dev_priv->use_mi_batchbuffer_start = param.value;
+		break;
+	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
+		dev_priv->tex_lru_log_granularity = param.value;
+		break;
+	case I915_SETPARAM_ALLOW_BATCHBUFFER:
+		dev_priv->allow_batchbuffer = param.value;
+		break;
+	default:
+		DRM_ERROR("unknown parameter %d\n", param.param);
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
diff -Nru a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/drm/i915_drm.h	2004-08-27 02:33:29 -07:00
@@ -0,0 +1,154 @@
+#ifndef _I915_DRM_H_
+#define _I915_DRM_H_
+
+/* Please note that modifications to all structs defined here are
+ * subject to backwards-compatibility constraints.
+ */
+
+#include "drm.h"
+
+/* Each region is a minimum of 16k, and there are at most 255 of them.
+ */
+#define I915_NR_TEX_REGIONS 255	/* table size 2k - maximum due to use
+				 * of chars for next/prev indices */
+#define I915_LOG_MIN_TEX_REGION_SIZE 14
+
+typedef struct _drm_i915_init {
+	enum {
+		I915_INIT_DMA = 0x01,
+		I915_CLEANUP_DMA = 0x02,
+		I915_RESUME_DMA = 0x03
+	} func;
+	unsigned int mmio_offset;
+	int sarea_priv_offset;
+	unsigned int ring_start;
+	unsigned int ring_end;
+	unsigned int ring_size;
+	unsigned int front_offset;
+	unsigned int back_offset;
+	unsigned int depth_offset;
+	unsigned int w;
+	unsigned int h;
+	unsigned int pitch;
+	unsigned int pitch_bits;
+	unsigned int back_pitch;
+	unsigned int depth_pitch;
+	unsigned int cpp;
+	unsigned int chipset;
+} drm_i915_init_t;
+
+typedef struct _drm_i915_sarea {
+	drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1];
+	int last_upload;	/* last time texture was uploaded */
+	int last_enqueue;	/* last time a buffer was enqueued */
+	int last_dispatch;	/* age of the most recently dispatched buffer */
+	int ctxOwner;		/* last context to upload state */
+	int texAge;
+	int pf_enabled;		/* is pageflipping allowed? */
+	int pf_active;
+	int pf_current_page;	/* which buffer is being displayed? */
+	int perf_boxes;		/* performance boxes to be displayed */
+} drm_i915_sarea_t;
+
+/* Flags for perf_boxes
+ */
+#define I915_BOX_RING_EMPTY    0x1
+#define I915_BOX_FLIP          0x2
+#define I915_BOX_WAIT          0x4
+#define I915_BOX_TEXTURE_LOAD  0x8
+#define I915_BOX_LOST_CONTEXT  0x10
+
+/* I915 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_IOCTL_I915_INIT		DRM_IOW( 0x40, drm_i915_init_t)
+#define DRM_IOCTL_I915_FLUSH		DRM_IO ( 0x41)
+#define DRM_IOCTL_I915_FLIP		DRM_IO ( 0x42)
+#define DRM_IOCTL_I915_BATCHBUFFER	DRM_IOW( 0x43, drm_i915_batchbuffer_t)
+#define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(0x44, drm_i915_irq_emit_t)
+#define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( 0x45, drm_i915_irq_wait_t)
+#define DRM_IOCTL_I915_GETPARAM         DRM_IOWR(0x46, drm_i915_getparam_t)
+#define DRM_IOCTL_I915_SETPARAM         DRM_IOW( 0x47, drm_i915_setparam_t)
+#define DRM_IOCTL_I915_ALLOC            DRM_IOWR(0x48, drm_i915_mem_alloc_t)
+#define DRM_IOCTL_I915_FREE             DRM_IOW( 0x49, drm_i915_mem_free_t)
+#define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( 0x4a, drm_i915_mem_init_heap_t)
+#define DRM_IOCTL_I915_CMDBUFFER	DRM_IOW( 0x4b, drm_i915_cmdbuffer_t)
+
+/* Allow drivers to submit batchbuffers directly to hardware, relying
+ * on the security mechanisms provided by hardware.
+ */
+typedef struct _drm_i915_batchbuffer {
+	int start;		/* agp offset */
+	int used;		/* nr bytes in use */
+	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
+	int DR4;		/* window origin for GFX_OP_DRAWRECT_INFO */
+	int num_cliprects;	/* mulitpass with multiple cliprects? */
+	drm_clip_rect_t __user *cliprects;	/* pointer to userspace cliprects */
+} drm_i915_batchbuffer_t;
+
+/* As above, but pass a pointer to userspace buffer which can be
+ * validated by the kernel prior to sending to hardware.
+ */
+typedef struct _drm_i915_cmdbuffer {
+	char __user *buf;	/* pointer to userspace command buffer */
+	int sz;			/* nr bytes in buf */
+	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
+	int DR4;		/* window origin for GFX_OP_DRAWRECT_INFO */
+	int num_cliprects;	/* mulitpass with multiple cliprects? */
+	drm_clip_rect_t __user *cliprects;	/* pointer to userspace cliprects */
+} drm_i915_cmdbuffer_t;
+
+/* Userspace can request & wait on irq's:
+ */
+typedef struct drm_i915_irq_emit {
+	int __user *irq_seq;
+} drm_i915_irq_emit_t;
+
+typedef struct drm_i915_irq_wait {
+	int irq_seq;
+} drm_i915_irq_wait_t;
+
+/* Ioctl to query kernel params:
+ */
+#define I915_PARAM_IRQ_ACTIVE            1
+#define I915_PARAM_ALLOW_BATCHBUFFER     2
+
+typedef struct drm_i915_getparam {
+	int param;
+	int __user *value;
+} drm_i915_getparam_t;
+
+/* Ioctl to set kernel params:
+ */
+#define I915_SETPARAM_USE_MI_BATCHBUFFER_START            1
+#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY             2
+#define I915_SETPARAM_ALLOW_BATCHBUFFER                   3
+
+typedef struct drm_i915_setparam {
+	int param;
+	int value;
+} drm_i915_setparam_t;
+
+/* A memory manager for regions of shared memory:
+ */
+#define I915_MEM_REGION_AGP 1
+
+typedef struct drm_i915_mem_alloc {
+	int region;
+	int alignment;
+	int size;
+	int __user *region_offset;	/* offset from start of fb or agp */
+} drm_i915_mem_alloc_t;
+
+typedef struct drm_i915_mem_free {
+	int region;
+	int region_offset;
+} drm_i915_mem_free_t;
+
+typedef struct drm_i915_mem_init_heap {
+	int region;
+	int size;
+	int start;
+} drm_i915_mem_init_heap_t;
+
+#endif				/* _I915_DRM_H_ */
diff -Nru a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/drm/i915_drv.c	2004-08-27 02:33:29 -07:00
@@ -0,0 +1,31 @@
+/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
+ */
+
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "i915.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#include "drm_agpsupport.h"
+#include "drm_auth.h"		/* is this needed? */
+#include "drm_bufs.h"
+#include "drm_context.h"	/* is this needed? */
+#include "drm_drawable.h"	/* is this needed? */
+#include "drm_drv.h"
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_irq.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_memory.h"		/*  */
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff -Nru a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/drm/i915_drv.h	2004-08-27 02:33:29 -07:00
@@ -0,0 +1,214 @@
+/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef _I915_DRV_H_
+#define _I915_DRV_H_
+
+typedef struct _drm_i915_ring_buffer {
+	int tail_mask;
+	unsigned long Start;
+	unsigned long End;
+	unsigned long Size;
+	u8 *virtual_start;
+	int head;
+	int tail;
+	int space;
+	drm_local_map_t map;
+} drm_i915_ring_buffer_t;
+
+struct mem_block {
+	struct mem_block *next;
+	struct mem_block *prev;
+	int start;
+	int size;
+	DRMFILE filp;		/* 0: free, -1: heap, other: real files */
+};
+
+typedef struct drm_i915_private {
+	drm_local_map_t *sarea;
+	drm_local_map_t *mmio_map;
+
+	drm_i915_sarea_t *sarea_priv;
+	drm_i915_ring_buffer_t ring;
+
+	void *hw_status_page;
+	unsigned long counter;
+	dma_addr_t dma_status_page;
+
+	int back_offset;
+	int front_offset;
+	int current_page;
+	int page_flipping;
+	int use_mi_batchbuffer_start;
+
+	wait_queue_head_t irq_queue;
+	atomic_t irq_received;
+	atomic_t irq_emitted;
+
+	int tex_lru_log_granularity;
+	int allow_batchbuffer;
+	struct mem_block *agp_heap;
+} drm_i915_private_t;
+
+				/* i915_dma.c */
+extern int i915_dma_init(DRM_IOCTL_ARGS);
+extern int i915_dma_cleanup(drm_device_t * dev);
+extern int i915_flush_ioctl(DRM_IOCTL_ARGS);
+extern int i915_batchbuffer(DRM_IOCTL_ARGS);
+extern int i915_flip_bufs(DRM_IOCTL_ARGS);
+extern int i915_getparam(DRM_IOCTL_ARGS);
+extern int i915_setparam(DRM_IOCTL_ARGS);
+extern int i915_cmdbuffer(DRM_IOCTL_ARGS);
+extern void i915_kernel_lost_context(drm_device_t * dev);
+
+/* i915_irq.c */
+extern int i915_irq_emit(DRM_IOCTL_ARGS);
+extern int i915_irq_wait(DRM_IOCTL_ARGS);
+extern int i915_wait_irq(drm_device_t * dev, int irq_nr);
+extern int i915_emit_irq(drm_device_t * dev);
+
+/* i915_mem.c */
+extern int i915_mem_alloc(DRM_IOCTL_ARGS);
+extern int i915_mem_free(DRM_IOCTL_ARGS);
+extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
+extern void i915_mem_takedown(struct mem_block **heap);
+extern void i915_mem_release(drm_device_t * dev,
+			     DRMFILE filp, struct mem_block *heap);
+
+#define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, reg)
+#define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, reg, val)
+#define I915_READ16(reg) 	DRM_READ16(dev_priv->mmio_map, reg)
+#define I915_WRITE16(reg,val)	DRM_WRITE16(dev_priv->mmio_map, reg, val)
+
+#define I915_VERBOSE 0
+
+#define RING_LOCALS	unsigned int outring, ringmask, outcount; \
+                        volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {				\
+	if (I915_VERBOSE)				\
+		DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",	\
+			  n, __FUNCTION__);		\
+	if (dev_priv->ring.space < n*4)			\
+		i915_wait_ring(dev, n*4, __FUNCTION__);		\
+	outcount = 0;					\
+	outring = dev_priv->ring.tail;			\
+	ringmask = dev_priv->ring.tail_mask;		\
+	virt = dev_priv->ring.virtual_start;		\
+} while (0)
+
+#define OUT_RING(n) do {					\
+	if (I915_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));	\
+	*(volatile unsigned int *)(virt + outring) = n;		\
+        outcount++;						\
+	outring += 4;						\
+	outring &= ringmask;					\
+} while (0)
+
+#define ADVANCE_LP_RING() do {						\
+	if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);	\
+	dev_priv->ring.tail = outring;					\
+	dev_priv->ring.space -= outcount * 4;				\
+	I915_WRITE(LP_RING + RING_TAIL, outring);			\
+} while(0)
+
+extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
+
+#define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
+#define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
+#define CMD_REPORT_HEAD			(7<<23)
+#define CMD_STORE_DWORD_IDX		((0x21<<23) | 0x1)
+#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
+
+#define INST_PARSER_CLIENT   0x00000000
+#define INST_OP_FLUSH        0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+#define BB1_START_ADDR_MASK   (~0x7)
+#define BB1_PROTECTED         (1<<0)
+#define BB1_UNPROTECTED       (0<<0)
+#define BB2_END_ADDR_MASK     (~0x7)
+
+#define I915REG_HWSTAM		0x02098
+#define I915REG_INT_IDENTITY_R	0x020a4
+#define I915REG_INT_MASK_R 	0x020a8
+#define I915REG_INT_ENABLE_R	0x020a0
+
+#define SRX_INDEX		0x3c4
+#define SRX_DATA		0x3c5
+#define SR01			1
+#define SR01_SCREEN_OFF 	(1<<5)
+
+#define PPCR			0x61204
+#define PPCR_ON			(1<<0)
+
+#define ADPA			0x61100
+#define ADPA_DPMS_MASK		(~(3<<10))
+#define ADPA_DPMS_ON		(0<<10)
+#define ADPA_DPMS_SUSPEND	(1<<10)
+#define ADPA_DPMS_STANDBY	(2<<10)
+#define ADPA_DPMS_OFF		(3<<10)
+
+#define NOPID                   0x2094
+#define LP_RING     		0x2030
+#define HP_RING     		0x2040
+#define RING_TAIL      		0x00
+#define TAIL_ADDR		0x001FFFF8
+#define RING_HEAD      		0x04
+#define HEAD_WRAP_COUNT     	0xFFE00000
+#define HEAD_WRAP_ONE       	0x00200000
+#define HEAD_ADDR           	0x001FFFFC
+#define RING_START     		0x08
+#define START_ADDR          	0x0xFFFFF000
+#define RING_LEN       		0x0C
+#define RING_NR_PAGES       	0x001FF000
+#define RING_REPORT_MASK    	0x00000006
+#define RING_REPORT_64K     	0x00000002
+#define RING_REPORT_128K    	0x00000004
+#define RING_NO_REPORT      	0x00000000
+#define RING_VALID_MASK     	0x00000001
+#define RING_VALID          	0x00000001
+#define RING_INVALID        	0x00000000
+
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR       (0x1<<1)
+#define SC_ENABLE_MASK          (0x1<<0)
+#define SC_ENABLE               (0x1<<0)
+
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK      (0xffff<<16)
+#define SCI_XMIN_MASK      (0xffff<<0)
+#define SCI_YMAX_MASK      (0xffff<<16)
+#define SCI_XMAX_MASK      (0xffff<<0)
+
+#define GFX_OP_SCISSOR_ENABLE	 ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT	 ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+
+#define MI_BATCH_BUFFER 	((0x30<<23)|1)
+#define MI_BATCH_BUFFER_START 	(0x31<<23)
+#define MI_BATCH_BUFFER_END 	(0xA<<23)
+#define MI_BATCH_NON_SECURE	(1)
+
+#define MI_WAIT_FOR_EVENT       ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
+#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+
+#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
+
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define ASYNC_FLIP                (1<<22)
+
+#define CMD_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+
+#endif
diff -Nru a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/drm/i915_irq.c	2004-08-27 03:36:17 -07:00
@@ -0,0 +1,161 @@
+/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "i915.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#define USER_INT_FLAG 0x2
+#define MAX_NOPID ((u32)~0)
+#define READ_BREADCRUMB(dev_priv)  (((u32*)(dev_priv->hw_status_page))[5])
+
+irqreturn_t DRM(irq_handler) (DRM_IRQ_ARGS) {
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u16 temp;
+
+	temp = I915_READ16(I915REG_INT_IDENTITY_R);
+	temp &= USER_INT_FLAG;
+
+	DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
+
+	if (temp == 0)
+		return IRQ_NONE;
+
+	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+	DRM_WAKEUP(&dev_priv->irq_queue);
+
+	return IRQ_HANDLED;
+}
+
+int i915_emit_irq(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 ret;
+	RING_LOCALS;
+
+	i915_kernel_lost_context(dev);
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	ret = dev_priv->counter;
+
+	BEGIN_LP_RING(2);
+	OUT_RING(0);
+	OUT_RING(GFX_OP_USER_INTERRUPT);
+	ADVANCE_LP_RING();
+
+	return ret;
+}
+
+int i915_wait_irq(drm_device_t * dev, int irq_nr)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int ret = 0;
+
+	DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
+		  READ_BREADCRUMB(dev_priv));
+
+	if (READ_BREADCRUMB(dev_priv) >= irq_nr)
+		return 0;
+
+	dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+
+	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
+		    READ_BREADCRUMB(dev_priv) >= irq_nr);
+
+	if (ret == DRM_ERR(EBUSY)) {
+		DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
+			  __FUNCTION__,
+			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
+	}
+
+	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+	return ret;
+}
+
+/* Needs the lock as it touches the ring.
+ */
+int i915_irq_emit(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_irq_emit_t emit;
+	int result;
+
+	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("i915_irq_emit called without lock held\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
+				 sizeof(emit));
+
+	result = i915_emit_irq(dev);
+
+	if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+/* Doesn't need the hardware lock.
+ */
+int i915_irq_wait(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_irq_wait_t irqwait;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
+				 sizeof(irqwait));
+
+	return i915_wait_irq(dev, irqwait.irq_seq);
+}
+
+/* drm_dma.h hooks
+*/
+void DRM(driver_irq_preinstall) (drm_device_t * dev) {
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	I915_WRITE16(I915REG_HWSTAM, 0xfffe);
+	I915_WRITE16(I915REG_INT_MASK_R, 0x0);
+	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+}
+
+void DRM(driver_irq_postinstall) (drm_device_t * dev) {
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
+	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+}
+
+void DRM(driver_irq_uninstall) (drm_device_t * dev) {
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	if (!dev_priv)
+		return;
+
+	I915_WRITE16(I915REG_HWSTAM, 0xffff);
+	I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
+	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+}
diff -Nru a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/drm/i915_mem.c	2004-08-27 17:05:27 -07:00
@@ -0,0 +1,347 @@
+/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
+ */
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "i915.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/* This memory manager is integrated into the global/local lru
+ * mechanisms used by the clients.  Specifically, it operates by
+ * setting the 'in_use' fields of the global LRU to indicate whether
+ * this region is privately allocated to a client.
+ *
+ * This does require the client to actually respect that field.
+ *
+ * Currently no effort is made to allocate 'private' memory in any
+ * clever way - the LRU information isn't used to determine which
+ * block to allocate, and the ring is drained prior to allocations --
+ * in other words allocation is expensive.
+ */
+static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_tex_region_t *list;
+	unsigned shift, nr;
+	unsigned start;
+	unsigned end;
+	unsigned i;
+	int age;
+
+	shift = dev_priv->tex_lru_log_granularity;
+	nr = I915_NR_TEX_REGIONS;
+
+	start = p->start >> shift;
+	end = (p->start + p->size - 1) >> shift;
+
+	age = ++sarea_priv->texAge;
+	list = sarea_priv->texList;
+
+	/* Mark the regions with the new flag and update their age.  Move
+	 * them to head of list to preserve LRU semantics.
+	 */
+	for (i = start; i <= end; i++) {
+		list[i].in_use = in_use;
+		list[i].age = age;
+
+		/* remove_from_list(i)
+		 */
+		list[(unsigned)list[i].next].prev = list[i].prev;
+		list[(unsigned)list[i].prev].next = list[i].next;
+
+		/* insert_at_head(list, i)
+		 */
+		list[i].prev = nr;
+		list[i].next = list[nr].next;
+		list[(unsigned)list[nr].next].prev = i;
+		list[nr].next = i;
+	}
+}
+
+/* Very simple allocator for agp memory, working on a static range
+ * already mapped into each client's address space.  
+ */
+
+static struct mem_block *split_block(struct mem_block *p, int start, int size,
+				     DRMFILE filp)
+{
+	/* Maybe cut off the start of an existing block */
+	if (start > p->start) {
+		struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock));
+		if (!newblock)
+			goto out;
+		newblock->start = start;
+		newblock->size = p->size - (start - p->start);
+		newblock->filp = NULL;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size -= newblock->size;
+		p = newblock;
+	}
+
+	/* Maybe cut off the end of an existing block */
+	if (size < p->size) {
+		struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock));
+		if (!newblock)
+			goto out;
+		newblock->start = start + size;
+		newblock->size = p->size - size;
+		newblock->filp = NULL;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size = size;
+	}
+
+      out:
+	/* Our block is in the middle */
+	p->filp = filp;
+	return p;
+}
+
+static struct mem_block *alloc_block(struct mem_block *heap, int size,
+				     int align2, DRMFILE filp)
+{
+	struct mem_block *p;
+	int mask = (1 << align2) - 1;
+
+	for (p = heap->next; p != heap; p = p->next) {
+		int start = (p->start + mask) & ~mask;
+		if (p->filp == NULL && start + size <= p->start + p->size)
+			return split_block(p, start, size, filp);
+	}
+
+	return NULL;
+}
+
+static struct mem_block *find_block(struct mem_block *heap, int start)
+{
+	struct mem_block *p;
+
+	for (p = heap->next; p != heap; p = p->next)
+		if (p->start == start)
+			return p;
+
+	return NULL;
+}
+
+static void free_block(struct mem_block *p)
+{
+	p->filp = NULL;
+
+	/* Assumes a single contiguous range.  Needs a special filp in
+	 * 'heap' to stop it being subsumed.
+	 */
+	if (p->next->filp == NULL) {
+		struct mem_block *q = p->next;
+		p->size += q->size;
+		p->next = q->next;
+		p->next->prev = p;
+		DRM_FREE(q, sizeof(*q));
+	}
+
+	if (p->prev->filp == NULL) {
+		struct mem_block *q = p->prev;
+		q->size += p->size;
+		q->next = p->next;
+		q->next->prev = q;
+		DRM_FREE(p, sizeof(*q));
+	}
+}
+
+/* Initialize.  How to check for an uninitialized heap?
+ */
+static int init_heap(struct mem_block **heap, int start, int size)
+{
+	struct mem_block *blocks = DRM_MALLOC(sizeof(*blocks));
+
+	if (!blocks)
+		return -ENOMEM;
+
+	*heap = DRM_MALLOC(sizeof(**heap));
+	if (!*heap) {
+		DRM_FREE(blocks, sizeof(*blocks));
+		return -ENOMEM;
+	}
+
+	blocks->start = start;
+	blocks->size = size;
+	blocks->filp = NULL;
+	blocks->next = blocks->prev = *heap;
+
+	memset(*heap, 0, sizeof(**heap));
+	(*heap)->filp = (DRMFILE) - 1;
+	(*heap)->next = (*heap)->prev = blocks;
+	return 0;
+}
+
+/* Free all blocks associated with the releasing file.
+ */
+void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
+{
+	struct mem_block *p;
+
+	if (!heap || !heap->next)
+		return;
+
+	for (p = heap->next; p != heap; p = p->next) {
+		if (p->filp == filp) {
+			p->filp = NULL;
+			mark_block(dev, p, 0);
+		}
+	}
+
+	/* Assumes a single contiguous range.  Needs a special filp in
+	 * 'heap' to stop it being subsumed.
+	 */
+	for (p = heap->next; p != heap; p = p->next) {
+		while (p->filp == NULL && p->next->filp == NULL) {
+			struct mem_block *q = p->next;
+			p->size += q->size;
+			p->next = q->next;
+			p->next->prev = p;
+			DRM_FREE(q, sizeof(*q));
+		}
+	}
+}
+
+/* Shutdown.
+ */
+void i915_mem_takedown(struct mem_block **heap)
+{
+	struct mem_block *p;
+
+	if (!*heap)
+		return;
+
+	for (p = (*heap)->next; p != *heap;) {
+		struct mem_block *q = p;
+		p = p->next;
+		DRM_FREE(q, sizeof(*q));
+	}
+
+	DRM_FREE(*heap, sizeof(**heap));
+	*heap = NULL;
+}
+
+static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
+{
+	switch (region) {
+	case I915_MEM_REGION_AGP:
+		return &dev_priv->agp_heap;
+	default:
+		return NULL;
+	}
+}
+
+/* IOCTL HANDLERS */
+
+int i915_mem_alloc(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_mem_alloc_t alloc;
+	struct mem_block *block, **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data,
+				 sizeof(alloc));
+
+	heap = get_heap(dev_priv, alloc.region);
+	if (!heap || !*heap)
+		return DRM_ERR(EFAULT);
+
+	/* Make things easier on ourselves: all allocations at least
+	 * 4k aligned.
+	 */
+	if (alloc.alignment < 12)
+		alloc.alignment = 12;
+
+	block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
+
+	if (!block)
+		return DRM_ERR(ENOMEM);
+
+	mark_block(dev, block, 1);
+
+	if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+int i915_mem_free(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_mem_free_t memfree;
+	struct mem_block *block, **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data,
+				 sizeof(memfree));
+
+	heap = get_heap(dev_priv, memfree.region);
+	if (!heap || !*heap)
+		return DRM_ERR(EFAULT);
+
+	block = find_block(*heap, memfree.region_offset);
+	if (!block)
+		return DRM_ERR(EFAULT);
+
+	if (block->filp != filp)
+		return DRM_ERR(EPERM);
+
+	mark_block(dev, block, 0);
+	free_block(block);
+	return 0;
+}
+
+int i915_mem_init_heap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_mem_init_heap_t initheap;
+	struct mem_block **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(initheap,
+				 (drm_i915_mem_init_heap_t __user *) data,
+				 sizeof(initheap));
+
+	heap = get_heap(dev_priv, initheap.region);
+	if (!heap)
+		return DRM_ERR(EFAULT);
+
+	if (*heap) {
+		DRM_ERROR("heap already initialized?");
+		return DRM_ERR(EFAULT);
+	}
+
+	return init_heap(heap, initheap.start, initheap.size);
+}
diff -Nru a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
--- a/drivers/char/drm/sis_mm.c	2004-07-16 07:14:58 -07:00
+++ b/drivers/char/drm/sis_mm.c	2004-08-27 17:05:27 -07:00
@@ -90,9 +90,10 @@
 {
 	drm_sis_mem_t fb;
 	struct sis_memreq req;
+	drm_sis_mem_t __user *argp = (void __user *)data;
 	int retval = 0;
 
-	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
+	DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
 
 	req.size = fb.size;
 	sis_malloc(&req);
@@ -111,7 +112,7 @@
 		fb.free = 0;
 	}
 
-	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
+	DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
 
 	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
 
@@ -123,7 +124,7 @@
 	drm_sis_mem_t fb;
 	int retval = 0;
 
-	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
+	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb));
 
 	if (!fb.free)
 		return DRM_ERR(EINVAL);
diff -Nru a/drivers/char/ftape/lowlevel/ftape-calibr.c b/drivers/char/ftape/lowlevel/ftape-calibr.c
--- a/drivers/char/ftape/lowlevel/ftape-calibr.c	2003-07-15 09:55:04 -07:00
+++ b/drivers/char/ftape/lowlevel/ftape-calibr.c	2004-08-27 00:02:38 -07:00
@@ -31,7 +31,10 @@
 #include <asm/io.h>
 #if defined(__alpha__)
 # include <asm/hwrpb.h>
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__x86_64__)
+# include <asm/msr.h>
+# include <asm/timex.h>
+#elif defined(__i386__)
 # include <linux/timex.h>
 #endif
 #include <linux/ftape.h>
@@ -45,7 +48,7 @@
 # error Ftape is not implemented for this architecture!
 #endif
 
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 static unsigned long ps_per_cycle = 0;
 #endif
 
@@ -72,7 +75,18 @@
 
 	asm volatile ("rpcc %0" : "=r" (r));
 	return r;
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__x86_64__)
+	unsigned long r;
+	rdtscl(r);
+	return r;
+#elif defined(__i386__)
+
+/*
+ * Note that there is some time between counter underflowing and jiffies
+ * increasing, so the code below won't always give correct output.
+ * -Vojtech
+ */
+
 	unsigned long flags;
 	__u16 lo;
 	__u16 hi;
@@ -89,9 +103,9 @@
 
 static unsigned int short_ftape_timestamp(void)
 {
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 	return ftape_timestamp();
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
 	unsigned int count;
  	unsigned long flags;
  
@@ -106,9 +120,9 @@
 
 static unsigned int diff(unsigned int t0, unsigned int t1)
 {
-#if defined(__alpha__)
-	return (t1 <= t0) ? t1 + (1UL << 32) - t0 : t1 - t0;
-#elif defined(__i386__) || defined(__x86_64__)
+#if defined(__alpha__) || defined(__x86_64__)
+	return (t1 - t0);
+#elif defined(__i386__)
 	/*
 	 * This is tricky: to work for both short and full ftape_timestamps
 	 * we'll have to discriminate between these.
@@ -122,9 +136,9 @@
 
 static unsigned int usecs(unsigned int count)
 {
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 	return (ps_per_cycle * count) / 1000000UL;
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
 	return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);
 #endif
 }
@@ -163,38 +177,13 @@
 
 static void init_clock(void)
 {
-#if defined(__i386__) || defined(__x86_64__)
-	unsigned int t;
-	int i;
 	TRACE_FUN(ft_t_any);
 
-	/*  Haven't studied on why, but there sometimes is a problem
-	 *  with the tick timer readout. The two bytes get swapped.
-	 *  This hack solves that problem by doing one extra input.
-	 */
-	for (i = 0; i < 1000; ++i) {
-		t = short_ftape_timestamp();
-		if (t > LATCH) {
-			inb_p(0x40);	/* get in sync again */
-			TRACE(ft_t_warn, "clock counter fixed");
-			break;
-		}
-	}
+#if defined(__x86_64__)
+	ps_per_cycle = 1000000000UL / cpu_khz;
 #elif defined(__alpha__)
-#if CONFIG_FT_ALPHA_CLOCK == 0
-#error You must define and set CONFIG_FT_ALPHA_CLOCK in 'make config' !
-#endif
 	extern struct hwrpb_struct *hwrpb;
-	TRACE_FUN(ft_t_any);
-
-	if (hwrpb->cycle_freq != 0) {
-		ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
-	} else {
-		/*
-		 * HELP:  Linux 2.0.x doesn't set cycle_freq on my noname !
-		 */
-		ps_per_cycle = (1000*1000*1000*1000UL) / CONFIG_FT_ALPHA_CLOCK;
-	}
+	ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
 #endif
 	TRACE_EXIT;
 }
@@ -213,7 +202,7 @@
 	unsigned int tc = 0;
 	unsigned int count;
 	unsigned int time;
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
 	unsigned int old_tc = 0;
 	unsigned int old_count = 1;
 	unsigned int old_time = 1;
@@ -255,7 +244,7 @@
 		tc = (1000 * time) / (count - 1);
 		TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
 			usecs(once), count - 1, usecs(multiple), tc);
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 		/*
 		 * Increase the calibration count exponentially until the
 		 * calibration time exceeds 100 ms.
@@ -263,7 +252,7 @@
 		if (time >= 100*1000) {
 			break;
 		}
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
 		/*
 		 * increase the count until the resulting time nears 2/HZ,
 		 * then the tc will drop sharply because we lose LATCH counts.
diff -Nru a/drivers/char/hvcs.c b/drivers/char/hvcs.c
--- a/drivers/char/hvcs.c	2004-08-23 01:14:44 -07:00
+++ b/drivers/char/hvcs.c	2004-08-27 00:02:38 -07:00
@@ -88,30 +88,6 @@
 #include <asm/vio.h>
 
 /*
- * 1.0.0 -> 1.1.0 Added kernel_thread scheduling methodology to driver to
- * replace wait_task constructs.
- *
- * 1.1.0 -> 1.2.0 Moved pi_buff initialization out of arch code into driver code
- * and added locking to share this buffer between hvcs_struct instances.  This
- * is because the page_size kmalloc can't be done with a spin_lock held.
- *
- * Also added sysfs attribute to manually disconnect the vty-server from the vty
- * due to stupid firmware behavior when opening the connection then sending data
- * then then quickly closing the connection would cause data loss on the
- * receiving side.  This required some reordering of the termination code.
- *
- * Fixed the hangup scenario and fixed memory leaks on module_exit.
- *
- * 1.2.0 -> 1.3.0 Moved from manual kernel thread creation & execution to
- * kthread construct which replaced in-kernel IPC for thread termination with
- * kthread_stop and kthread_should_stop.  Explicit wait_queue handling was
- * removed because kthread handles this.  Minor bug fix to postpone partner_info
- * clearing on hvcs_close until adapter removal to preserve context data for
- * printk on partner connection free.  Added lock to protect hvcs_structs so
- * that hvcs_struct instances aren't added or removed during list traversal.
- * Cleaned up comment style, added spaces after commas, and broke function
- * declaration lines to be under 80 columns.
- *
  * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00).
  * Removed braces around single statements following conditionals.  Removed '=
  * 0' after static int declarations since these default to zero.  Removed
@@ -123,17 +99,28 @@
  * SPIN_LOCK_UNLOCKED at declaration time rather than in hvcs_module_init().
  * Added spin_lock around list_del() in destroy_hvcs_struct() to protect the
  * list traversals from a deletion.  Removed '= NULL' from pointer declaration
- * statements since they are initialized NULL by default.  In hvcs_probe()
- * changed kmalloc(sizeof(*hvcsd),...) to kmalloc(sizeof(struct
- * hvcs_struct),...) because otherwise allocation would only be the size of a
- * pointer.  Removed wmb() instances from hvcs_try_write().  They probably
- * aren't needed with locking in place.  Added check and cleanup for
- * hvcs_pi_buff = kmalloc() in hvcs_module_init().  Exposed hvcs_struct.index
- * via a sysfs attribute so that the coupling between /dev/hvcs* and a
- * vty-server can be automatically determined.  Moved kobject_put() in hvcs_open
- * outside of the spin_unlock_irqrestore().
+ * statements since they are initialized NULL by default.  Removed wmb()
+ * instances from hvcs_try_write().  They probably aren't needed with locking in
+ * place.  Added check and cleanup for hvcs_pi_buff = kmalloc() in
+ * hvcs_module_init().  Exposed hvcs_struct.index via a sysfs attribute so that
+ * the coupling between /dev/hvcs* and a vty-server can be automatically
+ * determined.  Moved kobject_put() in hvcs_open outside of the
+ * spin_unlock_irqrestore().
+ *
+ * 1.3.1 -> 1.3.2 Changed method for determining hvcs_struct->index and had it
+ * align with how the tty layer always assigns the lowest index available.  This
+ * change resulted in a list of ints that denotes which indexes are available.
+ * Device additions and removals use the new hvcs_get_index() and
+ * hvcs_return_index() helper functions.  The list is created with
+ * hvsc_alloc_index_list() and it is destroyed with hvcs_free_index_list().
+ * Without these fixes hotplug vty-server adapter support goes crazy with this
+ * driver if the user removes a vty-server adapter.  Moved free_irq() outside of
+ * the hvcs_final_close() function in order to get it out of the spinlock.
+ * Rearranged hvcs_close().  Cleaned up some printks and did some housekeeping
+ * on the changelog.  Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from
+ * arch/ppc64/hvcserver.h.
  */
-#define HVCS_DRIVER_VERSION "1.3.1"
+#define HVCS_DRIVER_VERSION "1.3.2"
 
 MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
 MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");
@@ -159,9 +146,9 @@
 
 /*
  * We let Linux assign us a major number and we start the minors at zero.  There
- * is no intuitive mapping between minor number and the target partition.  The
- * mapping of minor number is related to the order the vty-servers are exposed
- * to this driver via the hvcs_probe function.
+ * is no intuitive mapping between minor number and the target vty-server
+ * adapter except that each new vty-server adapter is always assigned to the
+ * smallest minor number available.
  */
 #define HVCS_MINOR_START	0
 
@@ -173,9 +160,6 @@
  */
 #define __ALIGNED__	__attribute__((__aligned__(8)))
 
-/* Converged location code string length + 1 null terminator */
-#define CLC_LENGTH		80
-
 /*
  * How much data can firmware send with each hvc_put_chars()?  Maybe this
  * should be moved into an architecture specific area.
@@ -220,14 +204,25 @@
 static struct tty_driver *hvcs_tty_driver;
 
 /*
- * This is used to associate a vty-server, as it is exposed to this driver, with
- * a preallocated tty_struct.index.  The dev node and hvcs index numbers are not
- * re-used after device removal otherwise removing and adding a new one would
- * link a /dev/hvcs* entry to a different vty-server than it did before the
- * removal.  Incidentally, a newly exposed vty-server will always map to an
- * incrementally higher /dev/hvcs* entry than the last exposed vty-server.
+ * In order to be somewhat sane this driver always associates the hvcs_struct
+ * index element with the numerically equal tty->index.  This means that a
+ * hotplugged vty-server adapter will always map to the lowest index valued
+ * device node.  If vty-servers were hotplug removed from the system and then
+ * new ones added the new vty-server may have the largest slot number of all
+ * the vty-server adapters in the partition but it may have the lowest dev node
+ * index of all the adapters due to the hole left by the hotplug removed
+ * adapter.  There are a set of functions provided to get the lowest index for
+ * a new device as well as return the index to the list.  This list is allocated
+ * with a number of elements equal to the number of device nodes requested when
+ * the module was inserted.
  */
-static int hvcs_struct_count = -1;
+static int *hvcs_index_list;
+
+/*
+ * How large is the list?  This is kept for traversal since the list is
+ * dynamically created.
+ */
+static int hvcs_index_count;
 
 /*
  * Used by the khvcsd to pick up I/O operations when the kernel_thread is
@@ -235,7 +230,10 @@
  */
 static int hvcs_kicked;
 
-/* Used the the kthread construct for task operations */
+/*
+ * Use by the kthread construct for task operations like waking the sleeping
+ * thread and stopping the kthread.
+ */
 static struct task_struct *hvcs_task;
 
 /*
@@ -244,6 +242,7 @@
  */
 static unsigned long *hvcs_pi_buff;
 
+/* Only allow one hvcs_struct to use the hvcs_pi_buff at a time. */
 static spinlock_t hvcs_pi_lock = SPIN_LOCK_UNLOCKED;
 
 /* One vty-server per hvcs_struct */
@@ -286,7 +285,7 @@
 	int connected; /* is the vty-server currently connected to a vty? */
 	uint32_t p_unit_address; /* partner unit address */
 	uint32_t p_partition_ID; /* partner partition ID */
-	char p_location_code[CLC_LENGTH];
+	char p_location_code[HVCS_CLC_LENGTH + 1]; /* CLC + Null Term */
 	struct list_head next; /* list management */
 	struct vio_dev *vdev;
 };
@@ -522,6 +521,19 @@
 };
 MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
 
+static void hvcs_return_index(int index)
+{
+	/* Paranoia check */
+	if (!hvcs_index_list)
+		return;
+	if (index < 0 || index >= hvcs_index_count)
+		return;
+	if (hvcs_index_list[index] == -1)
+		return;
+	else
+		hvcs_index_list[index] = -1;
+}
+
 /* callback when the kboject ref count reaches zero */
 static void destroy_hvcs_struct(struct kobject *kobj)
 {
@@ -551,7 +563,8 @@
 
 	hvcsd->p_unit_address = 0;
 	hvcsd->p_partition_ID = 0;
-	memset(&hvcsd->p_location_code[0], 0x00, CLC_LENGTH);
+	hvcs_return_index(hvcsd->index);
+	memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1);
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 	spin_unlock(&hvcs_structs_lock);
@@ -561,11 +574,13 @@
 	kfree(hvcsd);
 }
 
-/* This function must be called with hvcsd->lock held. */
+/*
+ * This function must be called with hvcsd->lock held.  Do not free the irq in
+ * this function since it is called with the spinlock held.
+ */
 static void hvcs_final_close(struct hvcs_struct *hvcsd)
 {
 	vio_disable_interrupts(hvcsd->vdev);
-	free_irq(hvcsd->vdev->irq, hvcsd);
 
 	hvcsd->todo_mask = 0;
 
@@ -585,18 +600,43 @@
 	.release = destroy_hvcs_struct,
 };
 
+static int hvcs_get_index(void)
+{
+	int i;
+	/* Paranoia check */
+	if (!hvcs_index_list) {
+		printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n");
+		return -EFAULT;
+	}
+	/* Find the numerically lowest first free index. */
+	for(i = 0; i < hvcs_index_count; i++) {
+		if (hvcs_index_list[i] == -1) {
+			hvcs_index_list[i] = 0;
+			return i;
+		}
+	}
+	return -1;
+}
+
 static int __devinit hvcs_probe(
 	struct vio_dev *dev,
 	const struct vio_device_id *id)
 {
 	struct hvcs_struct *hvcsd;
+	int index;
 
 	if (!dev || !id) {
 		printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
 		return -EPERM;
 	}
 
-	hvcsd = kmalloc(sizeof(struct hvcs_struct), GFP_KERNEL);
+	/* early to avoid cleanup on failure */
+	index = hvcs_get_index();
+	if (index < 0) {
+		return -EFAULT;
+	}
+
+	hvcsd = kmalloc(sizeof(*hvcsd), GFP_KERNEL);
 	if (!hvcsd)
 		return -ENODEV;
 
@@ -612,7 +652,9 @@
 	hvcsd->vdev = dev;
 	dev->dev.driver_data = hvcsd;
 
-	hvcsd->index = ++hvcs_struct_count;
+	hvcsd->index = index;
+
+	/* hvcsd->index = ++hvcs_struct_count; */
 	hvcsd->chars_in_buffer = 0;
 	hvcsd->todo_mask = 0;
 	hvcsd->connected = 0;
@@ -641,7 +683,7 @@
 
 	hvcs_create_device_attrs(hvcsd);
 
-	printk(KERN_INFO "HVCS: Added vty-server@%X.\n", dev->unit_address);
+	printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
 
 	/*
 	 * DON'T enable interrupts here because there is no user to receive the
@@ -650,6 +692,8 @@
 	return 0;
 }
 
+
+
 static int __devexit hvcs_remove(struct vio_dev *dev)
 {
 	struct hvcs_struct *hvcsd = dev->dev.driver_data;
@@ -704,8 +748,8 @@
 	hvcsd->p_unit_address = pi->unit_address;
 	hvcsd->p_partition_ID  = pi->partition_ID;
 	clclength = strlen(&pi->location_code[0]);
-	if (clclength > CLC_LENGTH - 1)
-		clclength = CLC_LENGTH - 1;
+	if (clclength > HVCS_CLC_LENGTH)
+		clclength = HVCS_CLC_LENGTH;
 
 	/* copy the null-term char too */
 	strncpy(&hvcsd->p_location_code[0],
@@ -946,7 +990,8 @@
 	 * This function increments the kobject index.
 	 */
 	if (!(hvcsd = hvcs_get_by_index(tty->index))) {
-		printk(KERN_WARNING "HVCS: open failed, no index.\n");
+		printk(KERN_WARNING "HVCS: open failed, no device associated"
+				" with tty->index %d.\n", tty->index);
 		return -ENODEV;
 	}
 
@@ -984,7 +1029,7 @@
 
 	/*
 	 * This must be done outside of the spinlock because it requests irqs
-	 * and will grab the spinlcok and free the connection if it fails.
+	 * and will grab the spinlock and free the connection if it fails.
 	 */
 	if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
 		kobject_put(&hvcsd->kobj);
@@ -1012,7 +1057,7 @@
 open_success:
 	hvcs_kick();
 
-	printk(KERN_INFO "HVCS: vty-server@%X opened.\n",
+	printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
 		hvcsd->vdev->unit_address );
 
 	return 0;
@@ -1022,7 +1067,7 @@
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 	kobject_put(&hvcsd->kobj);
 
-	printk(KERN_WARNING "HVCS: HVCS partner connect failed.\n");
+	printk(KERN_WARNING "HVCS: partner connect failed.\n");
 	return retval;
 }
 
@@ -1031,6 +1076,7 @@
 	struct hvcs_struct *hvcsd;
 	unsigned long flags;
 	struct kobject *kobjp;
+	int irq = NO_IRQ;
 
 	/*
 	 * Is someone trying to close the file associated with this device after
@@ -1050,6 +1096,7 @@
 	hvcsd = tty->driver_data;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
+	kobjp = &hvcsd->kobj;
 	if (--hvcsd->open_count == 0) {
 
 		/*
@@ -1084,16 +1131,18 @@
 		}
 
 		hvcs_final_close(hvcsd);
-
+		irq = hvcsd->vdev->irq;
+		spin_unlock_irqrestore(&hvcsd->lock, flags);
+		free_irq(irq, hvcsd);
+		kobject_put(kobjp);
+		return;
 	} else if (hvcsd->open_count < 0) {
 		printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
 				" is missmanaged.\n",
-			hvcsd->vdev->unit_address, hvcsd->open_count);
+		hvcsd->vdev->unit_address, hvcsd->open_count);
 	}
-	kobjp = &hvcsd->kobj;
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
-
 	kobject_put(kobjp);
 }
 
@@ -1103,6 +1152,7 @@
 	unsigned long flags;
 	int temp_open_count;
 	struct kobject *kobjp;
+	int irq = NO_IRQ;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
 	/* Preserve this so that we know how many kobject refs to put */
@@ -1118,9 +1168,12 @@
 
 	/* Calling this will drop any buffered data on the floor. */
 	hvcs_final_close(hvcsd);
+	irq = hvcsd->vdev->irq;
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 
+	free_irq(irq, hvcsd);
+
 	/*
 	 * We need to kobject_put() for every open_count we have since the
 	 * tty_hangup() function doesn't invoke a close per open connection on a
@@ -1305,6 +1358,28 @@
 	.throttle = hvcs_throttle,
 };
 
+static int hvcs_alloc_index_list(int n)
+{
+	int i;
+	hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
+	if (!hvcs_index_list)
+		return -ENOMEM;
+	hvcs_index_count = n;
+	for(i = 0; i < hvcs_index_count; i++)
+		hvcs_index_list[i] = -1;
+	return 0;
+}
+
+static void hvcs_free_index_list(void)
+{
+	/* Paranoia check to be thorough. */
+	if (hvcs_index_list) {
+		kfree(hvcs_index_list);
+		hvcs_index_list = NULL;
+		hvcs_index_count = 0;
+	}
+}
+
 static int __init hvcs_module_init(void)
 {
 	int rc;
@@ -1323,6 +1398,9 @@
 	if (!hvcs_tty_driver)
 		return -ENOMEM;
 
+	if (hvcs_alloc_index_list(num_ttys_to_alloc))
+		return -ENOMEM;
+
 	hvcs_tty_driver->owner = THIS_MODULE;
 
 	hvcs_tty_driver->driver_name = hvcs_driver_name;
@@ -1353,6 +1431,7 @@
 	if (tty_register_driver(hvcs_tty_driver)) {
 		printk(KERN_ERR "HVCS: registration "
 			" as a tty driver failed.\n");
+		hvcs_free_index_list();
 		put_tty_driver(hvcs_tty_driver);
 		return rc;
 	}
@@ -1360,14 +1439,17 @@
 	hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!hvcs_pi_buff) {
 		tty_unregister_driver(hvcs_tty_driver);
+		hvcs_free_index_list();
 		put_tty_driver(hvcs_tty_driver);
 		return -ENOMEM;
 	}
 
 	hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
 	if (IS_ERR(hvcs_task)) {
-		printk("khvcsd creation failed.  Driver not loaded.\n");
+		printk(KERN_ERR "HVCS: khvcsd creation failed.  Driver not loaded.\n");
 		kfree(hvcs_pi_buff);
+		tty_unregister_driver(hvcs_tty_driver);
+		hvcs_free_index_list();
 		put_tty_driver(hvcs_tty_driver);
 		return -EIO;
 	}
@@ -1408,6 +1490,8 @@
 	vio_unregister_driver(&hvcs_vio_driver);
 
 	tty_unregister_driver(hvcs_tty_driver);
+
+	hvcs_free_index_list();
 
 	put_tty_driver(hvcs_tty_driver);
 
diff -Nru a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h
--- a/drivers/char/ip2/ip2types.h	2002-02-05 09:40:06 -08:00
+++ b/drivers/char/ip2/ip2types.h	2004-08-24 02:08:33 -07:00
@@ -49,6 +49,9 @@
 	short irq[IP2_MAX_BOARDS]; 
 	unsigned short addr[IP2_MAX_BOARDS];
 	int type[IP2_MAX_BOARDS];
+#ifdef CONFIG_PCI
+	struct pci_dev *pci_dev[IP2_MAX_BOARDS];
+#endif
 } ip2config_t;
 
 #endif
diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c
--- a/drivers/char/ip2main.c	2004-07-30 08:18:54 -07:00
+++ b/drivers/char/ip2main.c	2004-08-24 02:08:33 -07:00
@@ -440,6 +440,12 @@
 	// free memory
 	for (i = 0; i < IP2_MAX_BOARDS; i++) {
 		void *pB;
+#ifdef CONFIG_PCI
+		if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
+			pci_disable_device(ip2config.pci_dev[i]);
+			ip2config.pci_dev[i] = NULL;
+		}
+#endif
 		if ((pB = i2BoardPtrTable[i]) != 0 ) {
 			kfree ( pB );
 			i2BoardPtrTable[i] = NULL;
@@ -594,9 +600,14 @@
 							  PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
 				if (pci_dev_i != NULL) {
 					unsigned int addr;
-					unsigned char pci_irq;
 
+					if (pci_enable_device(pci_dev_i)) {
+						printk( KERN_ERR "IP2: can't enable PCI device at %s\n",
+							pci_name(pci_dev_i));
+						break;
+					}
 					ip2config.type[i] = PCI;
+					ip2config.pci_dev[i] = pci_dev_i;
 					status =
 					pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
 					if ( addr & 1 ) {
@@ -604,8 +615,6 @@
 					} else {
 						printk( KERN_ERR "IP2: PCI I/O address error\n");
 					}
-					status =
-					pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq);
 
 //		If the PCI BIOS assigned it, lets try and use it.  If we
 //		can't acquire it or it screws up, deal with it then.
@@ -614,7 +623,7 @@
 //						printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
 //						pci_irq = 0;
 //					}
-					ip2config.irq[i] = pci_irq;
+					ip2config.irq[i] = pci_dev_i->irq;
 				} else {	// ann error
 					ip2config.addr[i] = 0;
 					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
diff -Nru a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
--- a/drivers/char/ipmi/ipmi_poweroff.c	2004-08-23 01:15:22 -07:00
+++ b/drivers/char/ipmi/ipmi_poweroff.c	2004-08-25 18:44:31 -07:00
@@ -424,7 +424,7 @@
 	if (ready)
 		return;
 
-	rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, 0, &ipmi_user);
+	rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user);
 	if (rv) {
 		printk(KERN_ERR PFX "could not create IPMI user, error %d\n",
 		       rv);
diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
--- a/drivers/char/pcmcia/synclink_cs.c	2004-07-30 08:40:36 -07:00
+++ b/drivers/char/pcmcia/synclink_cs.c	2004-08-24 02:08:56 -07:00
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/pcmcia/synclink_cs.c
  *
- * $Id: synclink_cs.c,v 4.22 2004/06/01 20:27:46 paulkf Exp $
+ * $Id: synclink_cs.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $
  *
  * Device driver for Microgate SyncLink PC Card
  * multiprotocol serial adapter.
@@ -68,6 +68,7 @@
 #include <asm/types.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
+#include <linux/hdlc.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -76,12 +77,8 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -239,12 +236,11 @@
 	int netcount;
 	int dosyncppp;
 	spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-	struct ppp_device pppdev;
-	char netname[10];
+
+#ifdef CONFIG_HDLC
 	struct net_device *netdev;
-	struct net_device_stats netstats;
 #endif
+
 } MGSLPC_INFO;
 
 #define MGSLPC_MAGIC 0x5402
@@ -262,7 +258,7 @@
  *  FIXME: PPC has PVR defined in asm/reg.h.  For now we just undef it.
  */
 #undef PVR
-    
+
 #define RXFIFO  0
 #define TXFIFO  0
 #define STAR    0x20
@@ -398,18 +394,12 @@
 
 static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg);
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* SPPP/HDLC stuff */
-static void mgslpc_sppp_init(MGSLPC_INFO *info);
-static void mgslpc_sppp_delete(MGSLPC_INFO *info);
-static int  mgslpc_sppp_open(struct net_device *d);
-static int  mgslpc_sppp_close(struct net_device *d);
-static void mgslpc_sppp_tx_timeout(struct net_device *d);
-static int  mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *d);
-static void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size);
-static void mgslpc_sppp_tx_done(MGSLPC_INFO *info);
-static int  mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-struct net_device_stats *mgslpc_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(MGSLPC_INFO *info);
+static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size);
+static int  hdlcdev_init(MGSLPC_INFO *info);
+static void hdlcdev_exit(MGSLPC_INFO *info);
 #endif
 
 static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit);
@@ -494,7 +484,7 @@
 MODULE_LICENSE("GPL");
 
 static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 4.22 $";
+static char *driver_version = "$Revision: 4.26 $";
 
 static struct tty_driver *serial_driver;
 
@@ -1163,9 +1153,9 @@
 		info->drop_rts_on_tx_done = 0;
 	}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP	
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		mgslpc_sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else 
 #endif
 	{
@@ -1271,13 +1261,13 @@
 	info->icount.dcd++;
 	if (info->serial_signals & SerialSignal_DCD) {
 		info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP	
-		if (info->netcount)
-			sppp_reopen(info->netdev);
-#endif
 	}
 	else
 		info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+	if (info->netcount)
+		hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, info->netdev);
+#endif
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
@@ -2876,7 +2866,7 @@
 cleanup:			
 	if (retval) {
 		if (tty->count == 1)
-			info->tty = NULL;/* tty layer will release tty struct */
+			info->tty = NULL; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
@@ -2931,7 +2921,7 @@
 		if (info->icount.rxover)
 			ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover);
 		if (info->icount.rxcrc)
-			ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc);
+			ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc);
 	} else {
 		ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d",
 			      info->icount.tx, info->icount.rx);
@@ -3070,12 +3060,8 @@
 	printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n",
 		info->device_name, info->io_base, info->irq_level);
 
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#ifdef MODULE
-	if (info->dosyncppp)
-#endif
-		mgslpc_sppp_init(info);
+#ifdef CONFIG_HDLC
+	hdlcdev_init(info);
 #endif
 }
 
@@ -3090,9 +3076,8 @@
 				last->next_device = info->next_device;
 			else
 				mgslpc_device_list = info->next_device;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-			if (info->dosyncppp)
-				mgslpc_sppp_delete(info);
+#ifdef CONFIG_HDLC
+			hdlcdev_exit(info);
 #endif
 			release_resources(info);
 			kfree(info);
@@ -4021,9 +4006,12 @@
 				return_frame = 1;
 		}
 		framesize = 0;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		info->netstats.rx_errors++;
-		info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+		{
+			struct net_device_stats *stats = hdlc_stats(info->netdev);
+			stats->rx_errors++;
+			stats->rx_frame_errors++;
+		}
 #endif
 	} else
 		return_frame = 1;
@@ -4052,11 +4040,9 @@
 				++framesize;
 			}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-			if (info->netcount) {
-				/* pass frame to syncppp device */
-				mgslpc_sppp_rx_done(info, buf->data, framesize);
-			} 
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info, buf->data, framesize);
 			else
 #endif
 			{
@@ -4215,88 +4201,134 @@
 
 	spin_unlock_irqrestore(&info->lock,flags);
 	
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		mgslpc_sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else
 #endif
 		bh_transmit(info);
 }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* syncppp net device routines
+#ifdef CONFIG_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
  */
- 
-static void mgslpc_setup(struct net_device *dev)
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
 {
-	dev->open = mgslpc_sppp_open;
-	dev->stop = mgslpc_sppp_close;
-	dev->hard_start_xmit = mgslpc_sppp_tx;
-	dev->do_ioctl = mgslpc_sppp_ioctl;
-	dev->get_stats = mgslpc_net_stats;
-	dev->tx_timeout = mgslpc_sppp_tx_timeout;
-	dev->watchdog_timeo = 10*HZ;
-}
+	MGSLPC_INFO *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
 
-void mgslpc_sppp_init(MGSLPC_INFO *info)
-{
-	struct net_device *d;
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	sprintf(info->netname,"mgslp%d",info->line);
- 
-	d = alloc_netdev(0, info->netname, mgslpc_setup);
-	if (!d) {
-		printk(KERN_WARNING "%s: alloc_netdev failed.\n",
-						info->netname);
-		return;
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
 	}
 
-	info->if_ptr = &info->pppdev;
-	info->netdev = info->pppdev.dev = d;
-
-	d->base_addr = info->io_base;
-	d->irq = info->irq_level;
-	d->priv = info;
-
-	sppp_attach(&info->pppdev);
-	mgslpc_setup(d);
-
-	if (register_netdev(d)) {
-		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
-		sppp_detach(info->netdev);
-		info->netdev = NULL;
-		info->pppdev.dev = NULL;
-		free_netdev(d);
-		return;
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
 	}
 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_init()\n");	
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;;
+
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		mgslpc_program_hw(info);
+
+	return 0;
 }
 
-void mgslpc_sppp_delete(MGSLPC_INFO *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	MGSLPC_INFO *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
+	unsigned long flags;
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_delete(%s)\n",info->netname);	
-	unregister_netdev(info->netdev);
-	sppp_detach(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-	info->pppdev.dev = NULL;
+		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* copy data to device buffers */
+	memcpy(info->tx_buf, skb->data, skb->len);
+	info->tx_get = 0;
+	info->tx_put = info->tx_count = skb->len;
+
+	/* update network statistics */
+	stats->tx_packets++;
+	stats->tx_bytes += skb->len;
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	/* start hardware transmitter if necessary */
+	spin_lock_irqsave(&info->lock,flags);
+	if (!info->tx_active)
+	 	tx_start(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return 0;
 }
 
-int mgslpc_sppp_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
 {
-	MGSLPC_INFO *info = d->priv;
-	int err;
+	MGSLPC_INFO *info = dev_to_port(dev);
+	int rc;
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_open(%s)\n",info->netname);	
+		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
+
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
 
+	/* arbitrate between network and tty opens */
 	spin_lock_irqsave(&info->netlock, flags);
 	if (info->count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname);
+		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
 		spin_unlock_irqrestore(&info->netlock, flags);
 		return -EBUSY;
 	}
@@ -4304,142 +4336,297 @@
 	spin_unlock_irqrestore(&info->netlock, flags);
 
 	/* claim resources and init adapter */
-	if ((err = startup(info)) != 0)
-		goto open_fail;
-
-	/* allow syncppp module to do open processing */
-	if ((err = sppp_open(d)) != 0) {
-		shutdown(info);
-		goto open_fail;
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
 	}
 
+	/* assert DTR and RTS, apply hardware settings */
 	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
 	mgslpc_program_hw(info);
 
-	d->trans_start = jiffies;
-	netif_start_queue(d);
-	return 0;
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
 
-open_fail:
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return err;
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->lock, flags);
+	get_signals(info);
+	spin_unlock_irqrestore(&info->lock, flags);
+	hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+	return 0;
 }
 
-void mgslpc_sppp_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
 {
-	MGSLPC_INFO *info = dev->priv;
+	MGSLPC_INFO *info = dev_to_port(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_tx_timeout(%s)\n",info->netname);	
+		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
 
-	info->netstats.tx_errors++;
-	info->netstats.tx_aborted_errors++;
+	netif_stop_queue(dev);
 
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+	/* shutdown adapter and release resources */
+	shutdown(info);
 
-	netif_wake_queue(dev);
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	return 0;
 }
 
-int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	MGSLPC_INFO *info = dev->priv;
-	unsigned long flags;
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	MGSLPC_INFO *info = dev_to_port(dev);
+	unsigned int flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_tx(%s)\n",info->netname);	
+		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
 
-	netif_stop_queue(dev);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	info->tx_count = skb->len;
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
 
-	memcpy(info->tx_buf, skb->data, skb->len);
-	info->tx_get = 0;
-	info->tx_put = info->tx_count = skb->len;
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
 
-	info->netstats.tx_packets++;
-	info->netstats.tx_bytes += skb->len;
-	dev_kfree_skb(skb);
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
 
-	dev->trans_start = jiffies;
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
 
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active)
-	 	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
 
-	return 0;
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			mgslpc_program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
 }
 
-int mgslpc_sppp_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
 {
-	MGSLPC_INFO *info = d->priv;
+	MGSLPC_INFO *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_close(%s)\n",info->netname);	
+		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
 
-	/* shutdown adapter and release resources */
-	shutdown(info);
+	stats->tx_errors++;
+	stats->tx_aborted_errors++;
 
-	/* allow syncppp to do close processing */
-	sppp_close(d);
-	netif_stop_queue(d);
+	spin_lock_irqsave(&info->lock,flags);
+	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
 
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return 0;
+	netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(MGSLPC_INFO *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
 }
 
-void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size)
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size)
 {
 	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+	struct net_device_stats *stats = hdlc_stats(dev);
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_rx_done(%s)\n",info->netname);	
+		printk("hdlcdev_rx(%s)\n",dev->name);
+
 	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-			info->netname);
-		info->netstats.rx_dropped++;
+		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+		stats->rx_dropped++;
 		return;
 	}
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->protocol = htons(ETH_P_WAN_PPP);
-	skb->dev = info->netdev;
-	skb->mac.raw = skb->data;
-	info->netstats.rx_packets++;
-	info->netstats.rx_bytes += size;
+	skb->dev      = info->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = hdlc_type_trans(skb, skb->dev);
+
+	stats->rx_packets++;
+	stats->rx_bytes += size;
+
 	netif_rx(skb);
-	info->netdev->trans_start = jiffies;
-}
 
-void mgslpc_sppp_tx_done(MGSLPC_INFO *info)
-{
-	if (netif_queue_stopped(info->netdev))
-	    netif_wake_queue(info->netdev);
+	info->netdev->last_rx = jiffies;
 }
 
-struct net_device_stats *mgslpc_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(MGSLPC_INFO *info)
 {
-	MGSLPC_INFO *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_net_stats(%s)\n",info->netname);	
-	return &info->netstats;
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->base_addr = info->io_base;
+	dev->irq       = info->irq_level;
+
+	/* network layer callbacks and settings */
+	dev->do_ioctl       = hdlcdev_ioctl;
+	dev->open           = hdlcdev_open;
+	dev->stop           = hdlcdev_close;
+	dev->tx_timeout     = hdlcdev_tx_timeout;
+	dev->watchdog_timeo = 10*HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
 }
 
-int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(MGSLPC_INFO *info)
 {
-	MGSLPC_INFO *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-			info->netname, cmd );
-	return sppp_do_ioctl(dev, ifr, cmd);
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
 }
 
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
+
diff -Nru a/drivers/char/pty.c b/drivers/char/pty.c
--- a/drivers/char/pty.c	2004-06-29 23:02:10 -07:00
+++ b/drivers/char/pty.c	2004-08-24 02:08:49 -07:00
@@ -32,12 +32,6 @@
 #include <asm/bitops.h>
 #include <linux/devpts_fs.h>
 
-#if defined(CONFIG_LEGACY_PTYS) || defined(CONFIG_UNIX98_PTYS)
-
-#ifdef CONFIG_LEGACY_PTYS
-static struct tty_driver *pty_driver, *pty_slave_driver;
-#endif
-
 /* These are global because they are accessed in tty_io.c */
 #ifdef CONFIG_UNIX98_PTYS
 struct tty_driver *ptm_driver;
@@ -205,19 +199,6 @@
 	return ((count < N_TTY_BUF_SIZE/2) ? 0 : count);
 }
 
-/* 
- * Return the device number of a Unix98 PTY (only!).  This lets us open a
- * master pty with the multi-headed ptmx device, then find out which
- * one we got after it is open, with an ioctl.
- */
-#ifdef CONFIG_UNIX98_PTYS
-static int pty_get_device_number(struct tty_struct *tty, unsigned __user *value)
-{
-	unsigned int result = tty->index;
-	return put_user(result, value);
-}
-#endif
-
 /* Set the lock flag on a pty */
 static int pty_set_lock(struct tty_struct *tty, int __user * arg)
 {
@@ -231,41 +212,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_LEGACY_PTYS
-static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
-			 unsigned int cmd, unsigned long arg)
-{
-	if (!tty) {
-		printk("pty_ioctl called with NULL tty!\n");
-		return -EIO;
-	}
-	switch(cmd) {
-	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
-		return pty_set_lock(tty, (int __user *) arg);
-	}
-	return -ENOIOCTLCMD;
-}
-#endif
-
-#ifdef CONFIG_UNIX98_PTYS
-static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
-			    unsigned int cmd, unsigned long arg)
-{
-	if (!tty) {
-		printk("pty_unix98_ioctl called with NULL tty!\n");
-		return -EIO;
-	}
-	switch(cmd) {
-	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
-		return pty_set_lock(tty, (int __user *)arg);
-	case TIOCGPTN: /* Get PT Number */
-		return pty_get_device_number(tty, (unsigned int __user *)arg);
-	}
-
-	return -ENOIOCTLCMD;
-}
-#endif
-
 static void pty_flush_buffer(struct tty_struct *tty)
 {
 	struct tty_struct *to = tty->link;
@@ -322,42 +268,22 @@
 	.set_termios = pty_set_termios,
 };
 
-/* sysctl support for setting limits on the number of Unix98 ptys allocated.
-   Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. */
-#ifdef CONFIG_UNIX98_PTYS
-int pty_limit = NR_UNIX98_PTY_DEFAULT;
-static int pty_limit_min = 0;
-static int pty_limit_max = NR_UNIX98_PTY_MAX;
+/* Traditional BSD devices */
+#ifdef CONFIG_LEGACY_PTYS
+static struct tty_driver *pty_driver, *pty_slave_driver;
 
-ctl_table pty_table[] = {
-	{
-		.ctl_name	= PTY_MAX,
-		.procname	= "max",
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.data		= &pty_limit,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
-		.extra1		= &pty_limit_min,
-		.extra2		= &pty_limit_max,
-	}, {
-		.ctl_name	= PTY_NR,
-		.procname	= "nr",
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-	}, {
-		.ctl_name	= 0
+static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
+		return pty_set_lock(tty, (int __user *) arg);
 	}
-};
-#endif
-
-/* Initialization */
+	return -ENOIOCTLCMD;
+}
 
-static int __init pty_init(void)
+static void __init legacy_pty_init(void)
 {
-#ifdef CONFIG_LEGACY_PTYS
-	/* Traditional BSD devices */
 
 	pty_driver = alloc_tty_driver(NR_PTYS);
 	if (!pty_driver)
@@ -404,11 +330,58 @@
 		panic("Couldn't register pty driver");
 	if (tty_register_driver(pty_slave_driver))
 		panic("Couldn't register pty slave driver");
+}
+#else
+static inline void legacy_pty_init(void) { }
+#endif
 
-#endif /* CONFIG_LEGACY_PTYS */
-
+/* Unix98 devices */
 #ifdef CONFIG_UNIX98_PTYS
-	/* Unix98 devices */
+/*
+ * sysctl support for setting limits on the number of Unix98 ptys allocated.
+ * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
+ */
+int pty_limit = NR_UNIX98_PTY_DEFAULT;
+static int pty_limit_min = 0;
+static int pty_limit_max = NR_UNIX98_PTY_MAX;
+
+ctl_table pty_table[] = {
+	{
+		.ctl_name	= PTY_MAX,
+		.procname	= "max",
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.data		= &pty_limit,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &pty_limit_min,
+		.extra2		= &pty_limit_max,
+	}, {
+		.ctl_name	= PTY_NR,
+		.procname	= "nr",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	}, {
+		.ctl_name	= 0
+	}
+};
+
+static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
+			    unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
+		return pty_set_lock(tty, (int __user *)arg);
+	case TIOCGPTN: /* Get PT Number */
+		return put_user(tty->index, (unsigned int __user *)arg);
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static void __init unix98_pty_init(void)
+{
 	devfs_mk_dir("pts");
 	ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
 	if (!ptm_driver)
@@ -455,10 +428,15 @@
 		panic("Couldn't register Unix98 pts driver");
 
 	pty_table[1].data = &ptm_driver->refcount;
-#endif /* CONFIG_UNIX98_PTYS */
+}
+#else
+static inline void unix98_pty_init(void) { }
+#endif
 
+static int __init pty_init(void)
+{
+	legacy_pty_init();
+	unix98_pty_init();
 	return 0;
 }
 module_init(pty_init);
-
-#endif /* CONFIG_LEGACY_PTYS || CONFIG_UNIX98_PTYS */
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	2004-08-23 17:57:02 -07:00
+++ b/drivers/char/random.c	2004-08-24 02:09:05 -07:00
@@ -401,6 +401,7 @@
  */
 static struct entropy_store *random_state; /* The default global store */
 static struct entropy_store *sec_random_state; /* secondary store */
+static struct entropy_store *urandom_state; /* For urandom */
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 
@@ -493,6 +494,7 @@
 	/* mostly-read data: */
 	struct poolinfo poolinfo;
 	__u32		*pool;
+	const char	*name;
 
 	/* read-write data: */
 	spinlock_t lock ____cacheline_aligned_in_smp;
@@ -507,7 +509,8 @@
  *
  * Returns an negative error if there is a problem.
  */
-static int create_entropy_store(int size, struct entropy_store **ret_bucket)
+static int create_entropy_store(int size, const char *name,
+				struct entropy_store **ret_bucket)
 {
 	struct	entropy_store	*r;
 	struct	poolinfo	*p;
@@ -538,6 +541,7 @@
 	}
 	memset(r->pool, 0, POOLBYTES);
 	r->lock = SPIN_LOCK_UNLOCKED;
+	r->name = name;
 	*ret_bucket = r;
 	return 0;
 }
@@ -643,12 +647,8 @@
 	} else {
 		r->entropy_count += nbits;
 		if (nbits)
-			DEBUG_ENT("%04d %04d : added %d bits to %s\n",
-				  random_state->entropy_count,
-				  sec_random_state->entropy_count,
-				  nbits,
-				  r == sec_random_state ? "secondary" :
-				  r == random_state ? "primary" : "unknown");
+			DEBUG_ENT("Added %d entropy credits to %s, now %d\n",
+				  nbits, r->name, r->entropy_count);
 	}
 
 	spin_unlock_irqrestore(&r->lock, flags);
@@ -1328,8 +1328,7 @@
 			  "(%d of %d requested)\n",
 			  random_state->entropy_count,
 			  sec_random_state->entropy_count,
-			  r == sec_random_state ? "secondary" : "unknown",
-			  bytes * 8, nbytes * 8, r->entropy_count);
+			  r->name, bytes * 8, nbytes * 8, r->entropy_count);
 
 		bytes=extract_entropy(random_state, tmp, bytes,
 				      EXTRACT_ENTROPY_LIMIT);
@@ -1373,9 +1372,7 @@
 	DEBUG_ENT("%04d %04d : trying to extract %d bits from %s\n",
 		  random_state->entropy_count,
 		  sec_random_state->entropy_count,
-		  nbytes * 8,
-		  r == sec_random_state ? "secondary" :
-		  r == random_state ? "primary" : "unknown");
+		  nbytes * 8, r->name);
 
 	if (flags & EXTRACT_ENTROPY_LIMIT && nbytes >= r->entropy_count / 8)
 		nbytes = r->entropy_count / 8;
@@ -1388,12 +1385,8 @@
 	if (r->entropy_count < random_write_wakeup_thresh)
 		wake_up_interruptible(&random_write_wait);
 
-	DEBUG_ENT("%04d %04d : debiting %d bits from %s%s\n",
-		  random_state->entropy_count,
-		  sec_random_state->entropy_count,
-		  nbytes * 8,
-		  r == sec_random_state ? "secondary" :
-		  r == random_state ? "primary" : "unknown",
+	DEBUG_ENT("Debiting %d entropy credits from %s%s\n",
+		  nbytes * 8, r->name,
 		  flags & EXTRACT_ENTROPY_LIMIT ? "" : " (unlimited)");
 
 	spin_unlock_irqrestore(&r->lock, cpuflags);
@@ -1482,14 +1475,21 @@
  */
 void get_random_bytes(void *buf, int nbytes)
 {
-	if (sec_random_state)  
-		extract_entropy(sec_random_state, (char *) buf, nbytes, 
-				EXTRACT_ENTROPY_SECONDARY);
-	else if (random_state)
-		extract_entropy(random_state, (char *) buf, nbytes, 0);
-	else
+	struct entropy_store *r = urandom_state;
+	int flags = EXTRACT_ENTROPY_SECONDARY;
+
+	if (!r)
+		r = sec_random_state;
+	if (!r) {
+		r = random_state;
+		flags = 0;
+	}
+	if (!r) {
 		printk(KERN_NOTICE "get_random_bytes called before "
 				   "random driver initialization\n");
+		return;
+	}
+	extract_entropy(r, (char *) buf, nbytes, flags);
 }
 
 EXPORT_SYMBOL(get_random_bytes);
@@ -1533,14 +1533,19 @@
 {
 	int i;
 
-	if (create_entropy_store(DEFAULT_POOL_SIZE, &random_state))
+	if (create_entropy_store(DEFAULT_POOL_SIZE, "primary", &random_state))
 		goto err;
 	if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state))
 		goto err;
-	if (create_entropy_store(SECONDARY_POOL_SIZE, &sec_random_state))
+	if (create_entropy_store(SECONDARY_POOL_SIZE, "secondary",
+				 &sec_random_state))
+		goto err;
+	if (create_entropy_store(SECONDARY_POOL_SIZE, "urandom",
+				 &urandom_state))
 		goto err;
 	clear_entropy_store(random_state);
 	clear_entropy_store(sec_random_state);
+	clear_entropy_store(urandom_state);
 	init_std_data(random_state);
 	init_std_data(sec_random_state);
 #ifdef CONFIG_SYSCTL
@@ -1675,9 +1680,15 @@
 urandom_read(struct file * file, char __user * buf,
 		      size_t nbytes, loff_t *ppos)
 {
-	return extract_entropy(sec_random_state, buf, nbytes,
-			       EXTRACT_ENTROPY_USER |
-			       EXTRACT_ENTROPY_SECONDARY);
+	int flags = EXTRACT_ENTROPY_USER;
+	unsigned long cpuflags;
+
+	spin_lock_irqsave(&random_state->lock, cpuflags);
+	if (random_state->entropy_count > random_state->poolinfo.POOLBITS)
+		flags |= EXTRACT_ENTROPY_SECONDARY;
+	spin_unlock_irqrestore(&random_state->lock, cpuflags);
+
+	return extract_entropy(urandom_state, buf, nbytes, flags);
 }
 
 static unsigned int
@@ -1731,10 +1742,9 @@
 random_ioctl(struct inode * inode, struct file * file,
 	     unsigned int cmd, unsigned long arg)
 {
-	int *tmp, size, ent_count;
+	int size, ent_count;
 	int __user *p = (int __user *)arg;
 	int retval;
-	unsigned long flags;
 	
 	switch (cmd) {
 	case RNDGETENTCNT:
@@ -1755,40 +1765,6 @@
 		if (random_state->entropy_count >= random_read_wakeup_thresh)
 			wake_up_interruptible(&random_read_wait);
 		return 0;
-	case RNDGETPOOL:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		if (get_user(size, p) ||
-		    put_user(random_state->poolinfo.poolwords, p++))
-			return -EFAULT;
-		if (size < 0)
-			return -EFAULT;
-		if (size > random_state->poolinfo.poolwords)
-			size = random_state->poolinfo.poolwords;
-
-		/* prepare to atomically snapshot pool */
-
-		tmp = kmalloc(size * sizeof(__u32), GFP_KERNEL);
-
-		if (!tmp)
-			return -ENOMEM;
-
-		spin_lock_irqsave(&random_state->lock, flags);
-		ent_count = random_state->entropy_count;
-		memcpy(tmp, random_state->pool, size * sizeof(__u32));
-		spin_unlock_irqrestore(&random_state->lock, flags);
-
-		if (!copy_to_user(p, tmp, size * sizeof(__u32))) {
-			kfree(tmp);
-			return -EFAULT;
-		}
-
-		kfree(tmp);
-
-		if(put_user(ent_count, p++))
-			return -EFAULT;
-
-		return 0;
 	case RNDADDENTROPY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
@@ -1885,7 +1861,8 @@
 	struct entropy_store	*new_store, *old_store;
 	int			ret;
 	
-	if ((ret = create_entropy_store(poolsize, &new_store)))
+	if ((ret = create_entropy_store(poolsize, random_state->name,
+					&new_store)))
 		return ret;
 
 	add_entropy_words(new_store, random_state->pool,
@@ -2247,30 +2224,35 @@
 static spinlock_t ip_lock = SPIN_LOCK_UNLOCKED;
 static unsigned int ip_cnt;
 
-static struct keydata *__check_and_rekey(time_t time)
+static void rekey_seq_generator(void *private_)
 {
 	struct keydata *keyptr;
+	struct timeval 	tv;
+
+	do_gettimeofday(&tv);
+
 	spin_lock_bh(&ip_lock);
 	keyptr = &ip_keydata[ip_cnt&1];
-	if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) {
-		keyptr = &ip_keydata[1^(ip_cnt&1)];
-		keyptr->rekey_time = time;
-		get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
-		keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS;
-		mb();
-		ip_cnt++;
-	}
+
+	keyptr = &ip_keydata[1^(ip_cnt&1)];
+	keyptr->rekey_time = tv.tv_sec;
+	get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
+	keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS;
+	mb();
+	ip_cnt++;
+
 	spin_unlock_bh(&ip_lock);
-	return keyptr;
 }
 
+static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL);
+
 static inline struct keydata *check_and_rekey(time_t time)
 {
 	struct keydata *keyptr = &ip_keydata[ip_cnt&1];
 
 	rmb();
 	if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) {
-		keyptr = __check_and_rekey(time);
+		schedule_work(&rekey_work);
 	}
 
 	return keyptr;
diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c
--- a/drivers/char/rocket.c	2004-07-12 01:01:05 -07:00
+++ b/drivers/char/rocket.c	2004-08-24 02:08:59 -07:00
@@ -1283,11 +1283,7 @@
 	if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
 		return -EFAULT;
 
-#ifdef CAP_SYS_ADMIN
 	if (!capable(CAP_SYS_ADMIN))
-#else
-	if (!suser())
-#endif
 	{
 		if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
 			return -EPERM;
diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c
--- a/drivers/char/serial167.c	2004-02-22 19:09:24 -08:00
+++ b/drivers/char/serial167.c	2004-08-24 02:08:52 -07:00
@@ -2379,7 +2379,7 @@
                                        | CyPARITY| CyFRAME| CyOVERRUN;
 		/* info->timeout */
 
-		printk("ttyS%1d ", info->line);
+		printk("ttyS%d ", info->line);
 		port_num++;info++;
 		if(!(port_num & 7)){
 		    printk("\n               ");
diff -Nru a/drivers/char/sonypi.c b/drivers/char/sonypi.c
--- a/drivers/char/sonypi.c	2004-08-23 01:14:54 -07:00
+++ b/drivers/char/sonypi.c	2004-08-25 10:33:35 -07:00
@@ -67,7 +67,7 @@
 static inline void sonypi_initq(void) {
         sonypi_device.queue.head = sonypi_device.queue.tail = 0;
 	sonypi_device.queue.len = 0;
-	sonypi_device.queue.s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
+	sonypi_device.queue.s_lock = SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&sonypi_device.queue.proc_list);
 }
 
diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c
--- a/drivers/char/synclink.c	2004-07-26 14:29:20 -07:00
+++ b/drivers/char/synclink.c	2004-08-24 02:08:56 -07:00
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * $Id: synclink.c,v 4.24 2004/06/03 14:50:09 paulkf Exp $
+ * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -100,13 +100,10 @@
 #include <asm/types.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
+#include <linux/hdlc.h>
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -187,7 +184,6 @@
  */
  
 struct mgsl_struct {
-	void *if_ptr;	/* General purpose pointer (used by SPPP) */
 	int			magic;
 	int			flags;
 	int			count;		/* count of opens */
@@ -318,15 +314,13 @@
 	
 	struct	_input_signal_events	input_signal_events;
 
-	/* SPPP/Cisco HDLC device parts */
+	/* generic HDLC device parts */
 	int netcount;
 	int dosyncppp;
 	spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-	struct ppp_device pppdev;
-	char netname[10];
+
+#ifdef CONFIG_HDLC
 	struct net_device *netdev;
-	struct net_device_stats netstats;
 #endif
 };
 
@@ -734,18 +728,12 @@
 
 int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* SPPP/HDLC stuff */
-static void mgsl_sppp_init(struct mgsl_struct *info);
-static void mgsl_sppp_delete(struct mgsl_struct *info);
-int mgsl_sppp_open(struct net_device *d);
-int mgsl_sppp_close(struct net_device *d);
-void mgsl_sppp_tx_timeout(struct net_device *d);
-int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *d);
-void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size);
-void mgsl_sppp_tx_done(struct mgsl_struct *info);
-int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-struct net_device_stats *mgsl_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(struct mgsl_struct *info);
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
+static int  hdlcdev_init(struct mgsl_struct *info);
+static void hdlcdev_exit(struct mgsl_struct *info);
 #endif
 
 /*
@@ -911,7 +899,7 @@
 MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.24 $";
+static char *driver_version = "$Revision: 4.28 $";
 
 static int synclink_init_one (struct pci_dev *dev,
 				     const struct pci_device_id *ent);
@@ -1289,9 +1277,9 @@
 		info->drop_rts_on_tx_done = 0;
 	}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP	
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		mgsl_sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else 
 #endif
 	{
@@ -1352,12 +1340,12 @@
 			icount->dcd++;
 			if (status & MISCSTATUS_DCD) {
 				info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP	
-				if (info->netcount)
-					sppp_reopen(info->netdev);
-#endif
 			} else
 				info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev);
+#endif
 		}
 		if (status & MISCSTATUS_CTS_LATCHED)
 		{
@@ -3592,7 +3580,7 @@
 cleanup:			
 	if (retval) {
 		if (tty->count == 1)
-			info->tty = NULL;/* tty layer will release tty struct */
+			info->tty = NULL; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
@@ -4415,12 +4403,10 @@
 		     	info->max_frame_size );
 	}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#ifdef MODULE
-	if (info->dosyncppp)
-#endif
-		mgsl_sppp_init(info);
+#ifdef CONFIG_HDLC
+	hdlcdev_init(info);
 #endif
+
 }	/* end of mgsl_add_device() */
 
 /* mgsl_allocate_device()
@@ -4575,9 +4561,8 @@
 
 	info = mgsl_device_list;
 	while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		if (info->dosyncppp)
-			mgsl_sppp_delete(info);
+#ifdef CONFIG_HDLC
+		hdlcdev_exit(info);
 #endif
 		mgsl_release_resources(info);
 		tmp = info;
@@ -6750,9 +6735,12 @@
 				return_frame = 1;
 		}
 		framesize = 0;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		info->netstats.rx_errors++;
-		info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+		{
+			struct net_device_stats *stats = hdlc_stats(info->netdev);
+			stats->rx_errors++;
+			stats->rx_frame_errors++;
+		}
 #endif
 	} else
 		return_frame = 1;
@@ -6823,11 +6811,9 @@
 						*ptmp);
 			}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-			if (info->netcount) {
-				/* pass frame to syncppp device */
-				mgsl_sppp_rx_done(info,info->intermediate_rxbuffer,framesize);
-			} 
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
 			else
 #endif
 			{
@@ -7736,9 +7722,9 @@
 
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		mgsl_sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else
 #endif
 		mgsl_bh_transmit(info);
@@ -7819,79 +7805,125 @@
 	return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ;
 }			  
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* syncppp net device routines
+#ifdef CONFIG_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
  */
-static void mgsl_setup(struct net_device *dev)
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
 {
-	dev->open = mgsl_sppp_open;
-	dev->stop = mgsl_sppp_close;
-	dev->hard_start_xmit = mgsl_sppp_tx;
-	dev->do_ioctl = mgsl_sppp_ioctl;
-	dev->get_stats = mgsl_net_stats;
-	dev->tx_timeout = mgsl_sppp_tx_timeout;
-	dev->watchdog_timeo = 10*HZ;
-}
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
 
-static void mgsl_sppp_init(struct mgsl_struct *info)
-{
-	struct net_device *d;
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	sprintf(info->netname,"mgsl%d",info->line);
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
+	}
 
-	d = alloc_netdev(0, info->netname, mgsl_setup);
-	if (!d) {
-		printk(KERN_WARNING "%s: alloc_netdev failed.\n",
-						info->netname);
-		return;
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
 	}
 
-	info->if_ptr = &info->pppdev;
-	info->netdev = info->pppdev.dev = d;
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;;
 
-	d->base_addr = info->io_base;
-	d->irq = info->irq_level;
-	d->dma = info->dma_level;
-	d->priv = info;
-
-	sppp_attach(&info->pppdev);
-	mgsl_setup(d);
-
-	if (register_netdev(d)) {
-		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
-		sppp_detach(info->netdev);
-		info->netdev = NULL;
-		free_netdev(d);
-		return;
-	}
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		mgsl_program_hw(info);
 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_init()\n");	
+	return 0;
 }
 
-void mgsl_sppp_delete(struct mgsl_struct *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	struct mgsl_struct *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
+	unsigned long flags;
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_delete(%s)\n",info->netname);	
-	unregister_netdev(info->netdev);
-	sppp_detach(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-	info->pppdev.dev = NULL;
+		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* copy data to device buffers */
+	info->xmit_cnt = skb->len;
+	mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
+
+	/* update network statistics */
+	stats->tx_packets++;
+	stats->tx_bytes += skb->len;
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	/* start hardware transmitter if necessary */
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if (!info->tx_active)
+	 	usc_start_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	return 0;
 }
 
-int mgsl_sppp_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
 {
-	struct mgsl_struct *info = d->priv;
-	int err;
+	struct mgsl_struct *info = dev_to_port(dev);
+	int rc;
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_open(%s)\n",info->netname);	
+		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
 
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
+
+	/* arbitrate between network and tty opens */
 	spin_lock_irqsave(&info->netlock, flags);
 	if (info->count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname);
+		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
 		spin_unlock_irqrestore(&info->netlock, flags);
 		return -EBUSY;
 	}
@@ -7899,141 +7931,301 @@
 	spin_unlock_irqrestore(&info->netlock, flags);
 
 	/* claim resources and init adapter */
-	if ((err = startup(info)) != 0)
-		goto open_fail;
-
-	/* allow syncppp module to do open processing */
-	if ((err = sppp_open(d)) != 0) {
-		shutdown(info);
-		goto open_fail;
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
 	}
 
+	/* assert DTR and RTS, apply hardware settings */
 	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
 	mgsl_program_hw(info);
 
-	d->trans_start = jiffies;
-	netif_start_queue(d);
-	return 0;
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
 
-open_fail:
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return err;
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->irq_spinlock, flags);
+	usc_get_serial_signals(info);
+	spin_unlock_irqrestore(&info->irq_spinlock, flags);
+	hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+	return 0;
 }
 
-void mgsl_sppp_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
 {
-	struct mgsl_struct *info = dev->priv;
+	struct mgsl_struct *info = dev_to_port(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_tx_timeout(%s)\n",info->netname);	
+		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
 
-	info->netstats.tx_errors++;
-	info->netstats.tx_aborted_errors++;
+	netif_stop_queue(dev);
 
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_stop_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	/* shutdown adapter and release resources */
+	shutdown(info);
 
-	netif_wake_queue(dev);
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	return 0;
 }
 
-int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	struct mgsl_struct *info = dev->priv;
-	unsigned long flags;
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned int flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_tx(%s)\n",info->netname);	
+		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
 
-	netif_stop_queue(dev);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	info->xmit_cnt = skb->len;
-	mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
-	info->netstats.tx_packets++;
-	info->netstats.tx_bytes += skb->len;
-	dev_kfree_skb(skb);
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
 
-	dev->trans_start = jiffies;
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
 
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (!info->tx_active)
-	 	usc_start_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
 
-	return 0;
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
+
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
+
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			mgsl_program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
 }
 
-int mgsl_sppp_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
 {
-	struct mgsl_struct *info = d->priv;
+	struct mgsl_struct *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_close(%s)\n",info->netname);	
+		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
 
-	/* shutdown adapter and release resources */
-	shutdown(info);
+	stats->tx_errors++;
+	stats->tx_aborted_errors++;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_stop_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
-	/* allow syncppp to do close processing */
-	sppp_close(d);
-	netif_stop_queue(d);
+	netif_wake_queue(dev);
+}
 
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return 0;
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(struct mgsl_struct *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
 }
 
-void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size)
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
 {
 	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+	struct net_device_stats *stats = hdlc_stats(dev);
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_rx_done(%s)\n",info->netname);	
+		printk("hdlcdev_rx(%s)\n",dev->name);
+
 	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-			info->netname);
-		info->netstats.rx_dropped++;
+		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+		stats->rx_dropped++;
 		return;
 	}
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->protocol = htons(ETH_P_WAN_PPP);
-	skb->dev = info->netdev;
-	skb->mac.raw = skb->data;
-	info->netstats.rx_packets++;
-	info->netstats.rx_bytes += size;
+	skb->dev      = info->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = hdlc_type_trans(skb, skb->dev);
+
+	stats->rx_packets++;
+	stats->rx_bytes += size;
+
 	netif_rx(skb);
-	info->netdev->trans_start = jiffies;
-}
 
-void mgsl_sppp_tx_done(struct mgsl_struct *info)
-{
-	if (netif_queue_stopped(info->netdev))
-	    netif_wake_queue(info->netdev);
+	info->netdev->last_rx = jiffies;
 }
 
-struct net_device_stats *mgsl_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(struct mgsl_struct *info)
 {
-	struct mgsl_struct *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_net_stats(%s)\n",info->netname);	
-	return &info->netstats;
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->base_addr = info->io_base;
+	dev->irq       = info->irq_level;
+	dev->dma       = info->dma_level;
+
+	/* network layer callbacks and settings */
+	dev->do_ioctl       = hdlcdev_ioctl;
+	dev->open           = hdlcdev_open;
+	dev->stop           = hdlcdev_close;
+	dev->tx_timeout     = hdlcdev_tx_timeout;
+	dev->watchdog_timeo = 10*HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
 }
 
-int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(struct mgsl_struct *info)
 {
-	struct mgsl_struct *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-			info->netname, cmd );
-	return sppp_do_ioctl(dev, ifr, cmd);
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
 }
 
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
+
 
 static int __devinit synclink_init_one (struct pci_dev *dev,
 					const struct pci_device_id *ent)
diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
--- a/drivers/char/synclinkmp.c	2004-07-26 15:11:26 -07:00
+++ b/drivers/char/synclinkmp.c	2004-08-24 02:08:56 -07:00
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 4.22 2004/06/03 14:50:10 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -67,13 +67,10 @@
 #include <asm/types.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
+#include <linux/hdlc.h>
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -284,12 +281,11 @@
 	int netcount;
 	int dosyncppp;
 	spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-	struct ppp_device pppdev;
-	char netname[10];
+
+#ifdef CONFIG_HDLC
 	struct net_device *netdev;
-	struct net_device_stats netstats;
 #endif
+
 } SLMP_INFO;
 
 #define MGSL_MAGIC 0x5401
@@ -361,12 +357,7 @@
 #define TMCS	0x64
 #define TEPR	0x65
 
-/*
- *  FIXME: DAR here clashed with asm-ppc/reg.h and asm-sh/.../dma.h
- */
-#undef DAR
 /* DMA Controller Register macros */
-#define DAR	0x80
 #define DARL	0x80
 #define DARH	0x81
 #define DARB	0x82
@@ -498,7 +489,7 @@
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.22 $";
+static char *driver_version = "$Revision: 4.26 $";
 
 static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -553,20 +544,12 @@
 static void unthrottle(struct tty_struct * tty);
 static void set_break(struct tty_struct *tty, int break_state);
 
-/* sppp support and callbacks */
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-static void sppp_init(SLMP_INFO *info);
-static void sppp_delete(SLMP_INFO *info);
-static void sppp_rx_done(SLMP_INFO *info, char *buf, int size);
-static void sppp_tx_done(SLMP_INFO *info);
-
-static int  sppp_cb_open(struct net_device *d);
-static int  sppp_cb_close(struct net_device *d);
-static int  sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int  sppp_cb_tx(struct sk_buff *skb, struct net_device *dev);
-static void sppp_cb_tx_timeout(struct net_device *dev);
-static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(SLMP_INFO *info);
+static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size);
+static int  hdlcdev_init(SLMP_INFO *info);
+static void hdlcdev_exit(SLMP_INFO *info);
 #endif
 
 /* ioctl handlers */
@@ -800,7 +783,7 @@
 cleanup:
 	if (retval) {
 		if (tty->count == 1)
-			info->tty = NULL;/* tty layer will release tty struct */
+			info->tty = NULL; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
@@ -1627,79 +1610,125 @@
 	spin_unlock_irqrestore(&info->lock,flags);
 }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-
-/* syncppp support and callbacks */
-
-static void cb_setup(struct net_device *dev)
-{
-	dev->open = sppp_cb_open;
-	dev->stop = sppp_cb_close;
-	dev->hard_start_xmit = sppp_cb_tx;
-	dev->do_ioctl = sppp_cb_ioctl;
-	dev->get_stats = sppp_cb_net_stats;
-	dev->tx_timeout = sppp_cb_tx_timeout;
-	dev->watchdog_timeo = 10*HZ;
-}
+#ifdef CONFIG_HDLC
 
-static void sppp_init(SLMP_INFO *info)
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
 {
-	struct net_device *d;
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
 
-	sprintf(info->netname,"mgslm%dp%d",info->adapter_num,info->port_num);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	d = alloc_netdev(0, info->netname, cb_setup);
-	if (!d) {
-		printk(KERN_WARNING "%s: alloc_netdev failed.\n",
-						info->netname);
-		return;
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
 	}
 
-	info->if_ptr = &info->pppdev;
-	info->netdev = info->pppdev.dev = d;
-
-	d->irq = info->irq_level;
-	d->priv = info;
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
+	}
 
-	sppp_attach(&info->pppdev);
-	cb_setup(d);
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;;
 
-	if (register_netdev(d)) {
-		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
-		sppp_detach(info->netdev);
-		info->netdev = NULL;
-		info->pppdev.dev = NULL;
-		free_netdev(d);
-		return;
-	}
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		program_hw(info);
 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_init(%s)\n",info->netname);
+	return 0;
 }
 
-static void sppp_delete(SLMP_INFO *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	SLMP_INFO *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
+	unsigned long flags;
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_delete(%s)\n",info->netname);
-	unregister_netdev(info->netdev);
-	sppp_detach(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-	info->pppdev.dev = NULL;
+		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* copy data to device buffers */
+	info->tx_count = skb->len;
+	tx_load_dma_buffer(info, skb->data, skb->len);
+
+	/* update network statistics */
+	stats->tx_packets++;
+	stats->tx_bytes += skb->len;
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	/* start hardware transmitter if necessary */
+	spin_lock_irqsave(&info->lock,flags);
+	if (!info->tx_active)
+	 	tx_start(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return 0;
 }
 
-static int sppp_cb_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
 {
-	SLMP_INFO *info = d->priv;
-	int err;
+	SLMP_INFO *info = dev_to_port(dev);
+	int rc;
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_cb_open(%s)\n",info->netname);
+		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
+
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
 
+	/* arbitrate between network and tty opens */
 	spin_lock_irqsave(&info->netlock, flags);
 	if (info->count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: sppp_cb_open returning busy\n", info->netname);
+		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
 		spin_unlock_irqrestore(&info->netlock, flags);
 		return -EBUSY;
 	}
@@ -1707,141 +1736,300 @@
 	spin_unlock_irqrestore(&info->netlock, flags);
 
 	/* claim resources and init adapter */
-	if ((err = startup(info)) != 0)
-		goto open_fail;
-
-	/* allow syncppp module to do open processing */
-	if ((err = sppp_open(d)) != 0) {
-		shutdown(info);
-		goto open_fail;
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
 	}
 
+	/* assert DTR and RTS, apply hardware settings */
 	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
 	program_hw(info);
 
-	d->trans_start = jiffies;
-	netif_start_queue(d);
-	return 0;
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
 
-open_fail:
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return err;
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->lock, flags);
+	get_signals(info);
+	spin_unlock_irqrestore(&info->lock, flags);
+	hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+	return 0;
 }
 
-static void sppp_cb_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
 {
-	SLMP_INFO *info = dev->priv;
+	SLMP_INFO *info = dev_to_port(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_tx_timeout(%s)\n",info->netname);
+		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
 
-	info->netstats.tx_errors++;
-	info->netstats.tx_aborted_errors++;
+	netif_stop_queue(dev);
 
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+	/* shutdown adapter and release resources */
+	shutdown(info);
 
-	netif_wake_queue(dev);
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	return 0;
 }
 
-static int sppp_cb_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	SLMP_INFO *info = dev->priv;
-	unsigned long flags;
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned int flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_tx(%s)\n",info->netname);
+		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
 
-	netif_stop_queue(dev);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	info->tx_count = skb->len;
-	tx_load_dma_buffer(info, skb->data, skb->len);
-	info->netstats.tx_packets++;
-	info->netstats.tx_bytes += skb->len;
-	dev_kfree_skb(skb);
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
 
-	dev->trans_start = jiffies;
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
 
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active)
-	 	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
 
-	return 0;
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
+
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
+
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
 }
 
-static int sppp_cb_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
 {
-	SLMP_INFO *info = d->priv;
+	SLMP_INFO *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_cb_close(%s)\n",info->netname);
+		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
 
-	/* shutdown adapter and release resources */
-	shutdown(info);
+	stats->tx_errors++;
+	stats->tx_aborted_errors++;
 
-	/* allow syncppp to do close processing */
-	sppp_close(d);
-	netif_stop_queue(d);
+	spin_lock_irqsave(&info->lock,flags);
+	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
 
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return 0;
+	netif_wake_queue(dev);
 }
 
-static void sppp_rx_done(SLMP_INFO *info, char *buf, int size)
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(SLMP_INFO *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
+}
+
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size)
 {
 	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+	struct net_device_stats *stats = hdlc_stats(dev);
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_rx_done(%s)\n",info->netname);
+		printk("hdlcdev_rx(%s)\n",dev->name);
+
 	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-			info->netname);
-		info->netstats.rx_dropped++;
+		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+		stats->rx_dropped++;
 		return;
 	}
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->protocol = htons(ETH_P_WAN_PPP);
-	skb->dev = info->netdev;
-	skb->mac.raw = skb->data;
-	info->netstats.rx_packets++;
-	info->netstats.rx_bytes += size;
+	skb->dev      = info->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = hdlc_type_trans(skb, skb->dev);
+
+	stats->rx_packets++;
+	stats->rx_bytes += size;
+
 	netif_rx(skb);
-	info->netdev->trans_start = jiffies;
-}
 
-static void sppp_tx_done(SLMP_INFO *info)
-{
-	if (netif_queue_stopped(info->netdev))
-	    netif_wake_queue(info->netdev);
+	info->netdev->last_rx = jiffies;
 }
 
-static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(SLMP_INFO *info)
 {
-	SLMP_INFO *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("net_stats(%s)\n",info->netname);
-	return &info->netstats;
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->mem_start = info->phys_sca_base;
+	dev->mem_end   = info->phys_sca_base + SCA_BASE_SIZE - 1;
+	dev->irq       = info->irq_level;
+
+	/* network layer callbacks and settings */
+	dev->do_ioctl       = hdlcdev_ioctl;
+	dev->open           = hdlcdev_open;
+	dev->stop           = hdlcdev_close;
+	dev->tx_timeout     = hdlcdev_tx_timeout;
+	dev->watchdog_timeo = 10*HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
 }
 
-static int sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(SLMP_INFO *info)
 {
-	SLMP_INFO *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-			info->netname, cmd );
-	return sppp_do_ioctl(dev, ifr, cmd);
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
 }
 
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
 
 
 /* Return next bottom half action to perform.
@@ -2168,9 +2356,9 @@
 			set_signals(info);
 		}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 		if (info->netcount)
-			sppp_tx_done(info);
+			hdlcdev_tx_done(info);
 		else
 #endif
 		{
@@ -2358,12 +2546,12 @@
 			icount->dcd++;
 			if (status & SerialSignal_DCD) {
 				info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-				if (info->netcount)
-					sppp_reopen(info->netdev);
-#endif
 			} else
 				info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlc_set_carrier(status & SerialSignal_DCD, info->netdev);
+#endif
 		}
 		if (status & MISCSTATUS_CTS_LATCHED)
 		{
@@ -3616,9 +3804,8 @@
 		info->irq_level,
 		info->max_frame_size );
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-	if (info->dosyncppp)
-		sppp_init(info);
+#ifdef CONFIG_HDLC
+	hdlcdev_init(info);
 #endif
 }
 
@@ -3804,9 +3991,8 @@
 
 	info = synclinkmp_device_list;
 	while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		if (info->dosyncppp)
-			sppp_delete(info);
+#ifdef CONFIG_HDLC
+		hdlcdev_exit(info);
 #endif
 		reset_port(info);
 		if ( info->port_num == 0 ) {
@@ -4823,10 +5009,12 @@
 			info->icount.rxcrc++;
 
 		framesize = 0;
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		info->netstats.rx_errors++;
-		info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+		{
+			struct net_device_stats *stats = hdlc_stats(info->netdev);
+			stats->rx_errors++;
+			stats->rx_frame_errors++;
+		}
 #endif
 	}
 
@@ -4862,11 +5050,9 @@
 					index = 0;
 			}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-			if (info->netcount) {
-				/* pass frame to syncppp device */
-				sppp_rx_done(info,info->tmp_rx_buf,framesize);
-			}
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info,info->tmp_rx_buf,framesize);
 			else
 #endif
 			{
@@ -5384,9 +5570,9 @@
 
 	spin_unlock_irqrestore(&info->lock,flags);
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else
 #endif
 		bh_transmit(info);
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	2004-08-07 19:06:20 -07:00
+++ b/drivers/char/tty_io.c	2004-08-25 12:45:27 -07:00
@@ -142,6 +142,7 @@
 ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *);
 static unsigned int tty_poll(struct file *, poll_table *);
 static int tty_open(struct inode *, struct file *);
+static int ptmx_open(struct inode *, struct file *);
 static int tty_release(struct inode *, struct file *);
 int tty_ioctl(struct inode * inode, struct file * file,
 	      unsigned int cmd, unsigned long arg);
@@ -377,6 +378,19 @@
 	.fasync		= tty_fasync,
 };
 
+#ifdef CONFIG_UNIX98_PTYS
+static struct file_operations ptmx_fops = {
+	.llseek		= no_llseek,
+	.read		= tty_read,
+	.write		= tty_write,
+	.poll		= tty_poll,
+	.ioctl		= tty_ioctl,
+	.open		= ptmx_open,
+	.release	= tty_release,
+	.fasync		= tty_fasync,
+};
+#endif
+
 static struct file_operations console_fops = {
 	.llseek		= no_llseek,
 	.read		= tty_read,
@@ -749,6 +763,17 @@
 	return tty_write(file, buf, count, ppos);
 }
 
+static char ptychar[] = "pqrstuvwxyzabcde";
+
+static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
+{
+	int i = index + driver->name_base;
+	/* ->name is initialized to "ttyp", but "tty" is expected */
+	sprintf(p, "%s%c%x",
+			driver->subtype == PTY_TYPE_SLAVE ? "tty" : driver->name,
+			ptychar[i >> 4 & 0xf], i & 0xf);
+}
+
 static inline void tty_line_name(struct tty_driver *driver, int index, char *p)
 {
 	sprintf(p, "%s%d", driver->name, index + driver->name_base);
@@ -1358,53 +1383,13 @@
 		return -ENODEV;
 	}
 
-#ifdef CONFIG_UNIX98_PTYS
-	if (device == MKDEV(TTYAUX_MAJOR,2)) {
-		int idr_ret;
-
-		/* find a device that is not in use. */
-		down(&allocated_ptys_lock);
-		if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
-			up(&allocated_ptys_lock);
-			return -ENOMEM;
-		}
-		idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
-		if (idr_ret < 0) {
-			up(&allocated_ptys_lock);
-			if (idr_ret == -EAGAIN)
-				return -ENOMEM;
-			return -EIO;
-		}
-		if (index >= pty_limit) {
-			idr_remove(&allocated_ptys, index);
-			up(&allocated_ptys_lock);
-			return -EIO;
-		}
-		up(&allocated_ptys_lock);
-
-		driver = ptm_driver;
-		retval = init_dev(driver, index, &tty);
-		if (retval) {
-			down(&allocated_ptys_lock);
-			idr_remove(&allocated_ptys, index);
-			up(&allocated_ptys_lock);
-			return retval;
-		}
-
-		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
-		if (devpts_pty_new(tty->link))
-			retval = -ENOMEM;
-	} else
-#endif
-	{
-		driver = get_tty_driver(device, &index);
-		if (!driver)
-			return -ENODEV;
+	driver = get_tty_driver(device, &index);
+	if (!driver)
+		return -ENODEV;
 got_driver:
-		retval = init_dev(driver, index, &tty);
-		if (retval)
-			return retval;
-	}
+	retval = init_dev(driver, index, &tty);
+	if (retval)
+		return retval;
 
 	filp->private_data = tty;
 	file_move(filp, &tty->tty_files);
@@ -1431,15 +1416,6 @@
 		printk(KERN_DEBUG "error %d in opening %s...", retval,
 		       tty->name);
 #endif
-
-#ifdef CONFIG_UNIX98_PTYS
-		if (index != -1) {
-			down(&allocated_ptys_lock);
-			idr_remove(&allocated_ptys, index);
-			up(&allocated_ptys_lock);
-		}
-#endif
-
 		release_dev(filp);
 		if (retval != -ERESTARTSYS)
 			return retval;
@@ -1467,6 +1443,62 @@
 	return 0;
 }
 
+#ifdef CONFIG_UNIX98_PTYS
+static int ptmx_open(struct inode * inode, struct file * filp)
+{
+	struct tty_struct *tty;
+	int retval;
+	int index;
+	int idr_ret;
+
+	nonseekable_open(inode, filp);
+
+	/* find a device that is not in use. */
+	down(&allocated_ptys_lock);
+	if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
+		up(&allocated_ptys_lock);
+		return -ENOMEM;
+	}
+	idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
+	if (idr_ret < 0) {
+		up(&allocated_ptys_lock);
+		if (idr_ret == -EAGAIN)
+			return -ENOMEM;
+		return -EIO;
+	}
+	if (index >= pty_limit) {
+		idr_remove(&allocated_ptys, index);
+		up(&allocated_ptys_lock);
+		return -EIO;
+	}
+	up(&allocated_ptys_lock);
+
+	retval = init_dev(ptm_driver, index, &tty);
+	if (retval)
+		goto out;
+
+	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+	filp->private_data = tty;
+	file_move(filp, &tty->tty_files);
+
+	retval = -ENOMEM;
+	if (devpts_pty_new(tty->link))
+		goto out1;
+
+	check_tty_count(tty, "tty_open");
+	retval = ptm_driver->open(tty, filp);
+	if (!retval)
+		return 0;
+out1:
+	release_dev(filp);
+out:
+	down(&allocated_ptys_lock);
+	idr_remove(&allocated_ptys, index);
+	up(&allocated_ptys_lock);
+	return retval;
+}
+#endif
+
 static int tty_release(struct inode * inode, struct file * filp)
 {
 	lock_kernel();
@@ -2154,6 +2186,7 @@
 void tty_register_device(struct tty_driver *driver, unsigned index,
 			 struct device *device)
 {
+	char name[64];
 	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
 
 	if (index >= driver->num) {
@@ -2165,13 +2198,11 @@
 	devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
 			"%s%d", driver->devfs_name, index + driver->name_base);
 
-	/* we don't care about the ptys */
-	/* how nice to hide this behind some crappy interface.. */
-	if (driver->type != TTY_DRIVER_TYPE_PTY) {
-		char name[64];
+	if (driver->type == TTY_DRIVER_TYPE_PTY)
+		pty_line_name(driver, index, name);
+	else
 		tty_line_name(driver, index, name);
-		class_simple_device_add(tty_class, dev, device, name);
-	}
+	class_simple_device_add(tty_class, dev, device, name);
 }
 
 /**
@@ -2441,7 +2472,7 @@
 	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
 
 #ifdef CONFIG_UNIX98_PTYS
-	cdev_init(&ptmx_cdev, &tty_fops);
+	cdev_init(&ptmx_cdev, &ptmx_fops);
 	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 		panic("Couldn't register /dev/ptmx driver\n");
diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c
--- a/drivers/char/vt.c	2004-08-23 01:15:11 -07:00
+++ b/drivers/char/vt.c	2004-08-25 17:28:51 -07:00
@@ -1981,12 +1981,16 @@
 		hide_cursor(currcons);
 
 	while (!tty->stopped && count) {
-		c = *buf;
+		int orig = *buf;
+		c = orig;
 		buf++;
 		n++;
 		count--;
 
-		if (utf) {
+		/* Do no translation at all in control states */
+		if (vc_state != ESnormal) {
+			tc = c;
+		} else if (utf) {
 		    /* Combine UTF-8 into Unicode */
 		    /* Incomplete characters silently ignored */
 		    if(c > 0x7f) {
@@ -2086,7 +2090,7 @@
 			continue;
 		}
 		FLUSH
-		do_con_trol(tty, currcons, c);
+		do_con_trol(tty, currcons, orig);
 	}
 	FLUSH
 	console_conditional_schedule();
diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
--- a/drivers/char/watchdog/Kconfig	2004-07-28 21:58:54 -07:00
+++ b/drivers/char/watchdog/Kconfig	2004-08-03 11:13:56 -07:00
@@ -319,6 +319,12 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called machzwd.
 
+# PowerPC Architecture
+
+config 8xx_WDT
+	tristate "MPC8xx Watchdog Timer"
+	depends on WATCHDOG && 8xx
+
 # MIPS Architecture
 
 config INDYDOG
diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
--- a/drivers/char/watchdog/Makefile	2004-07-28 21:58:54 -07:00
+++ b/drivers/char/watchdog/Makefile	2004-08-03 11:13:56 -07:00
@@ -37,3 +37,4 @@
 obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
diff -Nru a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/watchdog/mpc8xx_wdt.c	2004-08-03 11:13:57 -07:00
@@ -0,0 +1,164 @@
+/*
+ * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
+ *
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/8xx_immap.h>
+#include <asm/uaccess.h>
+#include <syslib/m8xx_wdt.h>
+
+static unsigned long wdt_opened;
+static int wdt_status;
+
+static void mpc8xx_wdt_handler_disable(void)
+{
+	volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+	imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE);
+
+	printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
+}
+
+static void mpc8xx_wdt_handler_enable(void)
+{
+	volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+	imap->im_sit.sit_piscr |= PISCR_PIE | PISCR_PTE;
+
+	printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
+}
+
+static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(0, &wdt_opened))
+		return -EBUSY;
+
+	m8xx_wdt_reset();
+	mpc8xx_wdt_handler_disable();
+
+	return 0;
+}
+
+static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
+{
+	m8xx_wdt_reset();
+
+#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
+	mpc8xx_wdt_handler_enable();
+#endif
+
+	clear_bit(0, &wdt_opened);
+
+	return 0;
+}
+
+static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
+				loff_t * ppos)
+{
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	if (len)
+		m8xx_wdt_reset();
+
+	return len;
+}
+
+static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, unsigned long arg)
+{
+	int timeout;
+	static struct watchdog_info info = {
+		.options = WDIOF_KEEPALIVEPING,
+		.firmware_version = 0,
+		.identity = "MPC8xx watchdog",
+	};
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		if (put_user(wdt_status, (int *)arg))
+			return -EFAULT;
+		wdt_status &= ~WDIOF_KEEPALIVEPING;
+		break;
+
+	case WDIOC_GETTEMP:
+		return -EOPNOTSUPP;
+
+	case WDIOC_SETOPTIONS:
+		return -EOPNOTSUPP;
+
+	case WDIOC_KEEPALIVE:
+		m8xx_wdt_reset();
+		wdt_status |= WDIOF_KEEPALIVEPING;
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		return -EOPNOTSUPP;
+
+	case WDIOC_GETTIMEOUT:
+		timeout = m8xx_wdt_get_timeout();
+		if (put_user(timeout, (int *)arg))
+			return -EFAULT;
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static struct file_operations mpc8xx_wdt_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.write = mpc8xx_wdt_write,
+	.ioctl = mpc8xx_wdt_ioctl,
+	.open = mpc8xx_wdt_open,
+	.release = mpc8xx_wdt_release,
+};
+
+static struct miscdevice mpc8xx_wdt_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &mpc8xx_wdt_fops,
+};
+
+static int __init mpc8xx_wdt_init(void)
+{
+	return misc_register(&mpc8xx_wdt_miscdev);
+}
+
+static void __exit mpc8xx_wdt_exit(void)
+{
+	misc_deregister(&mpc8xx_wdt_miscdev);
+
+	m8xx_wdt_reset();
+	mpc8xx_wdt_handler_enable();
+}
+
+module_init(mpc8xx_wdt_init);
+module_exit(mpc8xx_wdt_exit);
+
+MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
+MODULE_DESCRIPTION("MPC8xx watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
--- a/drivers/char/watchdog/wdt_pci.c	2004-08-08 14:07:47 -07:00
+++ b/drivers/char/watchdog/wdt_pci.c	2004-08-24 02:08:32 -07:00
@@ -674,8 +674,8 @@
 out_misc:
 #ifdef CONFIG_WDT_501_PCI
 	misc_deregister(&temp_miscdev);
-#endif /* CONFIG_WDT_501_PCI */
 out_rbt:
+#endif /* CONFIG_WDT_501_PCI */
 	unregister_reboot_notifier(&wdtpci_notifier);
 out_irq:
 	free_irq(irq, &wdtpci_miscdev);
diff -Nru a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
--- a/drivers/cpufreq/Kconfig	2004-04-12 10:53:57 -07:00
+++ b/drivers/cpufreq/Kconfig	2004-08-24 10:27:44 -07:00
@@ -69,6 +69,21 @@
 
 	  If in doubt, say Y.
 
+config CPU_FREQ_GOV_ONDEMAND
+	tristate "'ondemand' cpufreq policy governor"
+	depends on CPU_FREQ
+	help
+	  'ondemand' - This driver adds a dynamic cpufreq policy governor.
+	  The governor does a periodic polling and 
+	  changes frequency based on the CPU utilization.
+	  The support for this governor depends on CPU capability to
+	  do fast frequency switching (i.e, very low latency frequency
+	  transitions). 
+
+	  For details, take a look at linux/Documentation/cpu-freq.
+
+	  If in doubt, say N.
+
 config CPU_FREQ_24_API
 	bool "/proc/sys/cpu/ interface (2.4. / OLD)"
 	depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE
diff -Nru a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
--- a/drivers/cpufreq/Makefile	2003-09-02 16:51:39 -07:00
+++ b/drivers/cpufreq/Makefile	2004-08-24 10:27:44 -07:00
@@ -5,6 +5,7 @@
 obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE)	+= cpufreq_performance.o
 obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE)	+= cpufreq_powersave.o
 obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)	+= cpufreq_userspace.o
+obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)	+= cpufreq_ondemand.o
 
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
diff -Nru a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/cpufreq/cpufreq_ondemand.c	2004-08-24 10:27:44 -07:00
@@ -0,0 +1,424 @@
+/*
+ *  drivers/cpufreq/cpufreq_ondemand.c
+ *
+ *  Copyright (C)  2001 Russell King
+ *            (C)  2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ *                      Jun Nakajima <jun.nakajima@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/cpufreq.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/sysfs.h>
+#include <linux/sched.h>
+#include <linux/kmod.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/config.h>
+#include <linux/kernel_stat.h>
+#include <linux/percpu.h>
+
+/*
+ * dbs is used in this file as a shortform for demandbased switching
+ * It helps to keep variable names smaller, simpler
+ */
+
+#define DEF_FREQUENCY_UP_THRESHOLD		(80)
+#define MIN_FREQUENCY_UP_THRESHOLD		(0)
+#define MAX_FREQUENCY_UP_THRESHOLD		(100)
+
+#define DEF_FREQUENCY_DOWN_THRESHOLD		(20)
+#define MIN_FREQUENCY_DOWN_THRESHOLD		(0)
+#define MAX_FREQUENCY_DOWN_THRESHOLD		(100)
+
+/* 
+ * The polling frequency of this governor depends on the capability of 
+ * the processor. Default polling frequency is 1000 times the transition
+ * latency of the processor. The governor will work on any processor with 
+ * transition latency <= 10mS, using appropriate sampling 
+ * rate.
+ * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
+ * this governor will not work.
+ * All times here are in uS.
+ */
+static unsigned int 				def_sampling_rate;
+#define MIN_SAMPLING_RATE			(def_sampling_rate / 2)
+#define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
+#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER	(1000)
+#define DEF_SAMPLING_DOWN_FACTOR		(10)
+#define TRANSITION_LATENCY_LIMIT		(10 * 1000)
+#define sampling_rate_in_HZ(x)			((x * HZ) / (1000 * 1000))
+
+static void do_dbs_timer(void *data);
+
+struct cpu_dbs_info_s {
+	struct cpufreq_policy 	*cur_policy;
+	unsigned int 		prev_cpu_idle_up;
+	unsigned int 		prev_cpu_idle_down;
+	unsigned int 		enable;
+};
+static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
+
+static unsigned int dbs_enable;	/* number of CPUs using this policy */
+
+static DECLARE_MUTEX 	(dbs_sem);
+static DECLARE_WORK	(dbs_work, do_dbs_timer, NULL);
+
+struct dbs_tuners {
+	unsigned int 		sampling_rate;
+	unsigned int		sampling_down_factor;
+	unsigned int		up_threshold;
+	unsigned int		down_threshold;
+};
+
+struct dbs_tuners dbs_tuners_ins = {
+	.up_threshold 		= DEF_FREQUENCY_UP_THRESHOLD,
+	.down_threshold 	= DEF_FREQUENCY_DOWN_THRESHOLD,
+	.sampling_down_factor 	= DEF_SAMPLING_DOWN_FACTOR,
+};
+
+/************************** sysfs interface ************************/
+static ssize_t show_current_freq(struct cpufreq_policy *policy, char *buf)
+{
+	return sprintf (buf, "%u\n", policy->cur);
+}
+
+static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
+{
+	return sprintf (buf, "%u\n", MAX_SAMPLING_RATE);
+}
+
+static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
+{
+	return sprintf (buf, "%u\n", MIN_SAMPLING_RATE);
+}
+
+#define define_one_ro(_name) 					\
+static struct freq_attr _name = { 				\
+	.attr = { .name = __stringify(_name), .mode = 0444 }, 	\
+	.show = show_##_name, 					\
+}
+
+define_one_ro(current_freq);
+define_one_ro(sampling_rate_max);
+define_one_ro(sampling_rate_min);
+
+/* cpufreq_ondemand Governor Tunables */
+#define show_one(file_name, object)					\
+static ssize_t show_##file_name						\
+(struct cpufreq_policy *unused, char *buf)				\
+{									\
+	return sprintf(buf, "%u\n", dbs_tuners_ins.object);		\
+}
+show_one(sampling_rate, sampling_rate);
+show_one(sampling_down_factor, sampling_down_factor);
+show_one(up_threshold, up_threshold);
+show_one(down_threshold, down_threshold);
+
+static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, 
+		const char *buf, size_t count)
+{
+	unsigned int input;
+	int ret;
+	ret = sscanf (buf, "%u", &input);
+	down(&dbs_sem);
+	if (ret != 1 )
+		goto out;
+
+	dbs_tuners_ins.sampling_down_factor = input;
+out:
+	up(&dbs_sem);
+	return count;
+}
+
+static ssize_t store_sampling_rate(struct cpufreq_policy *unused, 
+		const char *buf, size_t count)
+{
+	unsigned int input;
+	int ret;
+	ret = sscanf (buf, "%u", &input);
+	down(&dbs_sem);
+	if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE)
+		goto out;
+
+	dbs_tuners_ins.sampling_rate = input;
+out:
+	up(&dbs_sem);
+	return count;
+}
+
+static ssize_t store_up_threshold(struct cpufreq_policy *unused, 
+		const char *buf, size_t count)
+{
+	unsigned int input;
+	int ret;
+	ret = sscanf (buf, "%u", &input);
+	down(&dbs_sem);
+	if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || 
+			input < MIN_FREQUENCY_UP_THRESHOLD ||
+			input <= dbs_tuners_ins.down_threshold)
+		goto out;
+
+	dbs_tuners_ins.up_threshold = input;
+out:
+	up(&dbs_sem);
+	return count;
+}
+
+static ssize_t store_down_threshold(struct cpufreq_policy *unused, 
+		const char *buf, size_t count)
+{
+	unsigned int input;
+	int ret;
+	ret = sscanf (buf, "%u", &input);
+	down(&dbs_sem);
+	if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || 
+			input < MIN_FREQUENCY_DOWN_THRESHOLD ||
+			input >= dbs_tuners_ins.up_threshold)
+		goto out;
+
+	dbs_tuners_ins.down_threshold = input;
+out:
+	up(&dbs_sem);
+	return count;
+}
+
+#define define_one_rw(_name) 					\
+static struct freq_attr _name = { 				\
+	.attr = { .name = __stringify(_name), .mode = 0644 }, 	\
+	.show = show_##_name, 					\
+	.store = store_##_name, 				\
+}
+
+define_one_rw(sampling_rate);
+define_one_rw(sampling_down_factor);
+define_one_rw(up_threshold);
+define_one_rw(down_threshold);
+
+static struct attribute * dbs_attributes[] = {
+	&current_freq.attr,
+	&sampling_rate_max.attr,
+	&sampling_rate_min.attr,
+	&sampling_rate.attr,
+	&sampling_down_factor.attr,
+	&up_threshold.attr,
+	&down_threshold.attr,
+	NULL
+};
+
+static struct attribute_group dbs_attr_group = {
+	.attrs = dbs_attributes,
+	.name = "ondemand",
+};
+
+/************************** sysfs end ************************/
+
+static void dbs_check_cpu(int cpu)
+{
+	unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
+	unsigned int freq_down_step;
+	unsigned int freq_down_sampling_rate;
+	static int down_skip[NR_CPUS];
+	struct cpu_dbs_info_s *this_dbs_info;
+
+	this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
+	if (!this_dbs_info->enable)
+		return;
+
+	/* 
+	 * The default safe range is 20% to 80% 
+	 * Every sampling_rate, we check
+	 * 	- If current idle time is less than 20%, then we try to 
+	 * 	  increase frequency
+	 * Every sampling_rate*sampling_down_factor, we check
+	 * 	- If current idle time is more than 80%, then we try to
+	 * 	  decrease frequency
+	 *
+	 * Any frequency increase takes it to the maximum frequency. 
+	 * Frequency reduction happens at minimum steps of 
+	 * 5% of max_frequency 
+	 */
+	/* Check for frequency increase */
+	idle_ticks = kstat_cpu(cpu).cpustat.idle - 
+		this_dbs_info->prev_cpu_idle_up;
+	this_dbs_info->prev_cpu_idle_up = kstat_cpu(cpu).cpustat.idle;
+
+	up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
+			sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate) / 100;
+
+	if (idle_ticks < up_idle_ticks) {
+		__cpufreq_driver_target(this_dbs_info->cur_policy,
+			this_dbs_info->cur_policy->max, 
+			CPUFREQ_RELATION_H);
+		down_skip[cpu] = 0;
+		this_dbs_info->prev_cpu_idle_down = kstat_cpu(cpu).cpustat.idle;
+		return;
+	}
+
+	/* Check for frequency decrease */
+	down_skip[cpu]++;
+	if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
+		return;
+
+	idle_ticks = kstat_cpu(cpu).cpustat.idle - 
+		this_dbs_info->prev_cpu_idle_down;
+	down_skip[cpu] = 0;
+	this_dbs_info->prev_cpu_idle_down = kstat_cpu(cpu).cpustat.idle;
+
+	freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
+		dbs_tuners_ins.sampling_down_factor;
+	down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
+			sampling_rate_in_HZ(freq_down_sampling_rate) / 100;
+
+	if (idle_ticks > down_idle_ticks ) {
+		freq_down_step = (5 * this_dbs_info->cur_policy->max) / 100;
+		__cpufreq_driver_target(this_dbs_info->cur_policy,
+			this_dbs_info->cur_policy->cur - freq_down_step, 
+			CPUFREQ_RELATION_H);
+		return;
+	}
+}
+
+static void do_dbs_timer(void *data)
+{ 
+	int i;
+	down(&dbs_sem);
+	for (i = 0; i < NR_CPUS; i++)
+		if (cpu_online(i))
+			dbs_check_cpu(i);
+	schedule_delayed_work(&dbs_work, 
+			sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate));
+	up(&dbs_sem);
+} 
+
+static inline void dbs_timer_init(void)
+{
+	INIT_WORK(&dbs_work, do_dbs_timer, NULL);
+	schedule_work(&dbs_work);
+	return;
+}
+
+static inline void dbs_timer_exit(void)
+{
+	cancel_delayed_work(&dbs_work);
+	return;
+}
+
+static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+				   unsigned int event)
+{
+	unsigned int cpu = policy->cpu;
+	struct cpu_dbs_info_s *this_dbs_info;
+
+	this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
+
+	switch (event) {
+	case CPUFREQ_GOV_START:
+		if ((!cpu_online(cpu)) || 
+		    (!policy->cur))
+			return -EINVAL;
+
+		if (policy->cpuinfo.transition_latency >
+				(TRANSITION_LATENCY_LIMIT * 1000))
+			return -EINVAL;
+		if (this_dbs_info->enable) /* Already enabled */
+			break;
+		 
+		down(&dbs_sem);
+		this_dbs_info->cur_policy = policy;
+		
+		this_dbs_info->prev_cpu_idle_up = 
+				kstat_cpu(cpu).cpustat.idle;
+		this_dbs_info->prev_cpu_idle_down = 
+				kstat_cpu(cpu).cpustat.idle;
+		this_dbs_info->enable = 1;
+		sysfs_create_group(&policy->kobj, &dbs_attr_group);
+		dbs_enable++;
+		/*
+		 * Start the timerschedule work, when this governor
+		 * is used for first time
+		 */
+		if (dbs_enable == 1) {
+			/* policy latency is in nS. Convert it to uS first */
+			def_sampling_rate = (policy->cpuinfo.transition_latency / 1000) *
+					DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
+			dbs_tuners_ins.sampling_rate = def_sampling_rate;
+
+			dbs_timer_init();
+		}
+		
+		up(&dbs_sem);
+		break;
+
+	case CPUFREQ_GOV_STOP:
+		down(&dbs_sem);
+		this_dbs_info->enable = 0;
+		sysfs_remove_group(&policy->kobj, &dbs_attr_group);
+		dbs_enable--;
+		/*
+		 * Stop the timerschedule work, when this governor
+		 * is used for first time
+		 */
+		if (dbs_enable == 0) 
+			dbs_timer_exit();
+		
+		up(&dbs_sem);
+
+		break;
+
+	case CPUFREQ_GOV_LIMITS:
+		down(&dbs_sem);
+		if (policy->max < this_dbs_info->cur_policy->cur)
+			__cpufreq_driver_target(
+					this_dbs_info->cur_policy,
+				       	policy->max, CPUFREQ_RELATION_H);
+		else if (policy->min > this_dbs_info->cur_policy->cur)
+			__cpufreq_driver_target(
+					this_dbs_info->cur_policy,
+				       	policy->min, CPUFREQ_RELATION_L);
+		up(&dbs_sem);
+		break;
+	}
+	return 0;
+}
+
+struct cpufreq_governor cpufreq_gov_dbs = {
+	.name		= "ondemand",
+	.governor	= cpufreq_governor_dbs,
+	.owner		= THIS_MODULE,
+};
+EXPORT_SYMBOL(cpufreq_gov_dbs);
+
+static int __init cpufreq_gov_dbs_init(void)
+{
+	return cpufreq_register_governor(&cpufreq_gov_dbs);
+}
+
+static void __exit cpufreq_gov_dbs_exit(void)
+{
+	/* Make sure that the scheduled work is indeed not running */
+	flush_scheduled_work();
+
+	cpufreq_unregister_governor(&cpufreq_gov_dbs);
+}
+
+
+MODULE_AUTHOR ("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
+MODULE_DESCRIPTION ("'cpufreq_ondemand' - A dynamic cpufreq governor for "
+		"Low Latency Frequency Transition capable processors");
+MODULE_LICENSE ("GPL");
+
+module_init(cpufreq_gov_dbs_init);
+module_exit(cpufreq_gov_dbs_exit);
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig	2004-07-21 11:02:28 -07:00
+++ b/drivers/i2c/chips/Kconfig	2004-08-24 12:02:11 -07:00
@@ -299,4 +299,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-rtc8564.
 
+config ISP1301_OMAP
+	tristate "Philips ISP1301 with OMAP OTG"
+	depends on I2C && ARCH_OMAP_OTG
+	help
+	  If you say yes here you get support for the Philips ISP1301
+	  USB-On-The-Go transceiver working with the OMAP OTG controller.
+	  The ISP1301 is used in products including H2 and H3 development
+	  boards for Texas Instruments OMAP processors.
+	  
+	  This driver can also be built as a module.  If so, the module
+	  will be called isp1301_omap.
+
 endmenu
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile	2004-07-19 12:58:44 -07:00
+++ b/drivers/i2c/chips/Makefile	2004-08-24 12:02:11 -07:00
@@ -29,7 +29,9 @@
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
+obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
+
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	2004-07-22 00:50:51 -07:00
+++ b/drivers/i2c/chips/asb100.c	2004-08-12 13:00:14 -07:00
@@ -520,9 +520,9 @@
 	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
 }
 
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 #define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_in0_ref)
+device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 /* VRM */
 static ssize_t show_vrm(struct device *dev, char *buf)
diff -Nru a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/isp1301_omap.c	2004-08-24 12:02:11 -07:00
@@ -0,0 +1,1660 @@
+/*
+ * isp1301_omap - ISP 1301 USB transceiver, talking to OMAP OTG controller
+ *
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004 David Brownell
+ *
+ * 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 of the License, 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.
+ */
+#undef	DEBUG
+#undef	VERBOSE
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb.h>
+#include <linux/usb_otg.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <asm/irq.h>
+#include <asm/arch/usb.h>
+
+
+#ifndef	DEBUG
+#undef	VERBOSE
+#endif
+
+
+#define	DRIVER_VERSION	"24 August 2004"
+#define	DRIVER_NAME	(isp1301_driver.name)
+
+MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver");
+MODULE_LICENSE("GPL");
+
+struct isp1301 {
+	struct otg_transceiver	otg;
+	struct i2c_client	client;
+	void			(*i2c_release)(struct device *dev);
+
+	int			irq;
+
+	u32			last_otg_ctrl;
+	unsigned		working:1;
+
+	struct timer_list	timer;
+
+	/* use keventd context to change the state for us */
+	struct work_struct	work;
+	
+	unsigned long		todo;
+#		define WORK_UPDATE_ISP	0	/* update ISP from OTG */
+#		define WORK_UPDATE_OTG	1	/* update OTG from ISP */
+#		define WORK_HOST_RESUME	4	/* resume host */
+#		define WORK_TIMER	6	/* timer fired */
+#		define WORK_STOP	7	/* don't resubmit */
+};
+
+
+/* bits in OTG_CTRL_REG */
+
+#define	OTG_XCEIV_OUTPUTS \
+	(OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
+#define	OTG_XCEIV_INPUTS \
+	(OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
+#define	OTG_CTRL_BITS \
+	(OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
+	/* and OTG_PULLUP is sometimes written */
+
+#define	OTG_CTRL_MASK	(OTG_DRIVER_SEL| \
+	OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \
+	OTG_CTRL_BITS)
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_MACH_OMAP_H2
+
+/* board-specific PM hooks */
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/mach-types.h>
+
+
+#if	defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
+
+#include <asm/arch/tps65010.h>
+
+#else
+
+static inline int tps65010_set_vbus_draw(unsigned mA)
+{
+	pr_debug("tps65010: draw %d mA (STUB)\n", mA);
+	return 0;
+}
+
+#endif
+
+static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
+{
+	int status = tps65010_set_vbus_draw(mA);
+	if (status < 0)
+		pr_debug("  VBUS %d mA error %d\n", mA, status);
+}
+
+static void enable_vbus_source(struct isp1301 *isp)
+{
+	/* this board won't supply more than 8mA vbus power.
+	 * some boards can switch a 100ma "unit load" (or more).
+	 */
+}
+
+
+/* products will deliver OTG messages with LEDs, GUI, etc */
+static inline void notresponding(struct isp1301 *isp)
+{
+	printk(KERN_NOTICE "OTG device not responding.\n");
+}
+
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* only two addresses possible */
+#define	ISP_BASE		0x2c
+static unsigned short normal_i2c[] = {
+	ISP_BASE, ISP_BASE + 1,
+	I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver isp1301_driver;
+
+/* smbus apis are used for portability */
+
+static inline u8
+isp1301_get_u8(struct isp1301 *isp, u8 reg)
+{
+	return i2c_smbus_read_byte_data(&isp->client, reg + 0);
+}
+
+static inline int
+isp1301_get_u16(struct isp1301 *isp, u8 reg)
+{
+	return i2c_smbus_read_word_data(&isp->client, reg);
+}
+
+static inline int
+isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits)
+{
+	return i2c_smbus_write_byte_data(&isp->client, reg + 0, bits);
+}
+
+static inline int
+isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
+{
+	return i2c_smbus_write_byte_data(&isp->client, reg + 1, bits);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* identification */
+#define	ISP1301_VENDOR_ID		0x00	/* u16 read */
+#define	ISP1301_PRODUCT_ID		0x02	/* u16 read */
+#define	ISP1301_BCD_DEVICE		0x14	/* u16 read */
+
+#define	I2C_VENDOR_ID_PHILIPS		0x04cc
+#define	I2C_PRODUCT_ID_PHILIPS_1301	0x1301
+
+/* operational registers */
+#define	ISP1301_MODE_CONTROL_1		0x04	/* u8 read, set, +1 clear */
+#	define	MC1_SPEED_REG		(1 << 0)
+#	define	MC1_SUSPEND_REG		(1 << 1)
+#	define	MC1_DAT_SE0		(1 << 2)
+#	define	MC1_TRANSPARENT		(1 << 3)
+#	define	MC1_BDIS_ACON_EN	(1 << 4)
+#	define	MC1_OE_INT_EN		(1 << 5)
+#	define	MC1_UART_EN		(1 << 6)
+#	define	MC1_MASK		0x7f
+#define	ISP1301_MODE_CONTROL_2		0x12	/* u8 read, set, +1 clear */
+#	define	MC2_GLOBAL_PWR_DN	(1 << 0)
+#	define	MC2_SPD_SUSP_CTRL	(1 << 1)
+#	define	MC2_BI_DI		(1 << 2)
+#	define	MC2_TRANSP_BDIR0	(1 << 3)
+#	define	MC2_TRANSP_BDIR1	(1 << 4)
+#	define	MC2_AUDIO_EN		(1 << 5)
+#	define	MC2_PSW_EN		(1 << 6)
+#	define	MC2_EN2V7		(1 << 7)
+#define	ISP1301_OTG_CONTROL_1		0x06	/* u8 read, set, +1 clear */
+#	define	OTG1_DP_PULLUP		(1 << 0)
+#	define	OTG1_DM_PULLUP		(1 << 1)
+#	define	OTG1_DP_PULLDOWN	(1 << 2)
+#	define	OTG1_DM_PULLDOWN	(1 << 3)
+#	define	OTG1_ID_PULLDOWN	(1 << 4)
+#	define	OTG1_VBUS_DRV		(1 << 5)
+#	define	OTG1_VBUS_DISCHRG	(1 << 6)
+#	define	OTG1_VBUS_CHRG		(1 << 7)
+#define	ISP1301_OTG_STATUS		0x10	/* u8 readonly */
+#	define	OTG_B_SESS_END		(1 << 6)
+#	define	OTG_B_SESS_VLD		(1 << 7)
+
+#define	ISP1301_INTERRUPT_SOURCE	0x08	/* u8 read */
+#define	ISP1301_INTERRUPT_LATCH		0x0A	/* u8 read, set, +1 clear */
+
+#define	ISP1301_INTERRUPT_FALLING	0x0C	/* u8 read, set, +1 clear */
+#define	ISP1301_INTERRUPT_RISING	0x0E	/* u8 read, set, +1 clear */
+
+/* same bitfields in all interrupt registers */
+#	define	INTR_VBUS_VLD		(1 << 0)
+#	define	INTR_SESS_VLD		(1 << 1)
+#	define	INTR_DP_HI		(1 << 2)
+#	define	INTR_ID_GND		(1 << 3)
+#	define	INTR_DM_HI		(1 << 4)
+#	define	INTR_ID_FLOAT		(1 << 5)
+#	define	INTR_BDIS_ACON		(1 << 6)
+#	define	INTR_CR_INT		(1 << 7)
+
+/*-------------------------------------------------------------------------*/
+
+static const char *state_string(enum usb_otg_state state)
+{
+	switch (state) {
+	case OTG_STATE_A_IDLE:		return "a_idle";
+	case OTG_STATE_A_WAIT_VRISE:	return "a_wait_vrise";
+	case OTG_STATE_A_WAIT_BCON:	return "a_wait_bcon";
+	case OTG_STATE_A_HOST:		return "a_host";
+	case OTG_STATE_A_SUSPEND:	return "a_suspend";
+	case OTG_STATE_A_PERIPHERAL:	return "a_peripheral";
+	case OTG_STATE_A_WAIT_VFALL:	return "a_wait_vfall";
+	case OTG_STATE_A_VBUS_ERR:	return "a_vbus_err";
+	case OTG_STATE_B_IDLE:		return "b_idle";
+	case OTG_STATE_B_SRP_INIT:	return "b_srp_init";
+	case OTG_STATE_B_PERIPHERAL:	return "b_peripheral";
+	case OTG_STATE_B_WAIT_ACON:	return "b_wait_acon";
+	case OTG_STATE_B_HOST:		return "b_host";
+	default:			return "UNDEFINED";
+	}
+}
+
+static inline const char *state_name(struct isp1301 *isp)
+{
+	return state_string(isp->otg.state);
+}
+
+#ifdef	VERBOSE
+#define	dev_vdbg			dev_dbg
+#else
+#define	dev_vdbg(dev, fmt, arg...)	do{}while(0)
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* NOTE:  some of this ISP1301 setup is specific to H2 boards;
+ * not everything is guarded by board-specific checks, or even using
+ * omap_usb_config data to deduce MC1_DAT_SE0 and MC2_BI_DI.
+ *
+ * ALSO:  this currently doesn't use ISP1301 low-power modes
+ * while OTG is running.
+ */
+
+static void power_down(struct isp1301 *isp)
+{
+	isp->otg.state = OTG_STATE_UNDEFINED;
+
+	// isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
+	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND_REG);
+
+	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN);
+	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+}
+
+static void power_up(struct isp1301 *isp)
+{
+	// isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
+	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND_REG);
+	
+	/* do this only when cpu is driving transceiver,
+	 * so host won't see a low speed device...
+	 */
+	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+}
+
+#define	NO_HOST_SUSPEND
+
+static int host_suspend(struct isp1301 *isp)
+{
+#ifdef	NO_HOST_SUSPEND
+	return 0;
+#else
+	struct device	*dev;
+
+	if (!isp->otg.host)
+		return -ENODEV;
+
+	/* Currently ASSUMES only the OTG port matters;
+	 * other ports could be active...
+	 */
+	dev = isp->otg.host->controller;
+	return dev->driver->suspend(dev, 3, 0);
+#endif
+}
+
+static int host_resume(struct isp1301 *isp)
+{
+#ifdef	NO_HOST_SUSPEND
+	return 0;
+#else
+	struct device	*dev;
+
+	if (!isp->otg.host)
+		return -ENODEV;
+
+	dev = isp->otg.host->controller;
+	return dev->driver->resume(dev, 0);
+#endif
+}
+
+static int gadget_suspend(struct isp1301 *isp)
+{
+	isp->otg.gadget->b_hnp_enable = 0;
+	isp->otg.gadget->a_hnp_support = 0;
+	isp->otg.gadget->a_alt_hnp_support = 0;
+	return usb_gadget_vbus_disconnect(isp->otg.gadget);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define	TIMER_MINUTES	10
+#define	TIMER_JIFFIES	(TIMER_MINUTES * 60 * HZ)
+
+/* Almost all our I2C messaging comes from a work queue's task context.
+ * NOTE: guaranteeing certain response times might mean we shouldn't
+ * share keventd's work queue; a realtime task might be safest.
+ */
+void
+isp1301_defer_work(struct isp1301 *isp, int work)
+{
+	int status;
+
+	if (isp && !test_and_set_bit(work, &isp->todo)) {
+		(void) get_device(&isp->client.dev);
+		status = schedule_work(&isp->work);
+		if (!status && !isp->working)
+			dev_vdbg(&isp->client.dev,
+				"work item %d may be lost\n", work);
+	}
+}
+
+/* called from irq handlers */
+static void a_idle(struct isp1301 *isp, const char *tag)
+{
+	if (isp->otg.state == OTG_STATE_A_IDLE)
+		return;
+
+	isp->otg.default_a = 1;
+	if (isp->otg.host) {
+		isp->otg.host->is_b_host = 0;
+		host_suspend(isp);
+	}
+	if (isp->otg.gadget) {
+		isp->otg.gadget->is_a_peripheral = 1;
+		gadget_suspend(isp);
+	}
+	isp->otg.state = OTG_STATE_A_IDLE;
+	isp->last_otg_ctrl = OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+	pr_debug("  --> %s/%s\n", state_name(isp), tag);
+}
+
+/* called from irq handlers */
+static void b_idle(struct isp1301 *isp, const char *tag)
+{
+	if (isp->otg.state == OTG_STATE_B_IDLE)
+		return;
+
+	isp->otg.default_a = 0;
+	if (isp->otg.host) {
+		isp->otg.host->is_b_host = 1;
+		host_suspend(isp);
+	}
+	if (isp->otg.gadget) {
+		isp->otg.gadget->is_a_peripheral = 0;
+		gadget_suspend(isp);
+	}
+	isp->otg.state = OTG_STATE_B_IDLE;
+	isp->last_otg_ctrl = OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+	pr_debug("  --> %s/%s\n", state_name(isp), tag);
+}
+
+static void
+dump_regs(struct isp1301 *isp, const char *label)
+{
+#ifdef	DEBUG
+	u8	ctrl = isp1301_get_u8(isp, ISP1301_OTG_CONTROL_1);
+	u8	status = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+	u8	src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
+
+	pr_debug("otg: %06x, %s %s, otg/%02x stat/%02x.%02x\n",
+		OTG_CTRL_REG, label, state_name(isp),
+		ctrl, status, src);
+	/* mode control and irq enables don't change much */
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_USB_OTG
+
+/*
+ * The OMAP OTG controller handles most of the OTG state transitions.
+ *
+ * We translate isp1301 outputs (mostly voltage comparator status) into
+ * OTG inputs; OTG outputs (mostly pullup/pulldown controls) and HNP state
+ * flags into isp1301 inputs ... and infer state transitions.
+ */
+
+#ifdef	VERBOSE
+
+static void check_state(struct isp1301 *isp, const char *tag)
+{
+	enum usb_otg_state	state = OTG_STATE_UNDEFINED;
+	u8			fsm = OTG_TEST_REG & 0x0ff;
+	unsigned		extra = 0;
+
+	switch (fsm) {
+
+	/* default-b */
+	case 0x0:
+		state = OTG_STATE_B_IDLE;
+		break;
+	case 0x3:
+	case 0x7:
+		extra = 1;
+	case 0x1:
+		state = OTG_STATE_B_PERIPHERAL;
+		break;
+	case 0x11:
+		state = OTG_STATE_B_SRP_INIT;
+		break;
+
+	/* extra dual-role default-b states */
+	case 0x12:
+	case 0x13:
+	case 0x16:
+		extra = 1;
+	case 0x17:
+		state = OTG_STATE_B_WAIT_ACON;
+		break;
+	case 0x34:
+		state = OTG_STATE_B_HOST;
+		break;
+
+	/* default-a */
+	case 0x36:
+		state = OTG_STATE_A_IDLE;
+		break;
+	case 0x3c:
+		state = OTG_STATE_A_WAIT_VFALL;
+		break;
+	case 0x7d:
+		state = OTG_STATE_A_VBUS_ERR;
+		break;
+	case 0x9e:
+	case 0x9f:
+		extra = 1;
+	case 0x89:
+		state = OTG_STATE_A_PERIPHERAL;
+		break;
+	case 0xb7:
+		state = OTG_STATE_A_WAIT_VRISE;
+		break;
+	case 0xb8:
+		state = OTG_STATE_A_WAIT_BCON;
+		break;
+	case 0xb9:
+		state = OTG_STATE_A_HOST;
+		break;
+	case 0xba:
+		state = OTG_STATE_A_SUSPEND;
+		break;
+	default:
+		break;
+	}
+	if (isp->otg.state == state && !extra)
+		return;
+	pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
+		state_string(state), fsm, state_name(isp), OTG_CTRL_REG);
+}
+
+#else
+
+static inline void check_state(struct isp1301 *isp, const char *tag) { }
+
+#endif
+
+/* outputs from ISP1301_INTERRUPT_SOURCE */
+static void update_otg1(struct isp1301 *isp, u8 int_src)
+{
+	u32	otg_ctrl;
+
+	otg_ctrl = OTG_CTRL_REG
+			& OTG_CTRL_MASK
+			& ~OTG_XCEIV_INPUTS
+			& ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD);
+	if (int_src & INTR_SESS_VLD)
+		otg_ctrl |= OTG_ASESSVLD;
+	else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) {
+		a_idle(isp, "vfall");
+		otg_ctrl &= ~OTG_CTRL_BITS;
+	}
+	if (int_src & INTR_VBUS_VLD)
+		otg_ctrl |= OTG_VBUSVLD;
+	if (int_src & INTR_ID_GND) {		/* default-A */
+		if (isp->otg.state == OTG_STATE_B_IDLE
+				|| isp->otg.state == OTG_STATE_UNDEFINED) {
+			a_idle(isp, "init");
+			return;
+		}
+	} else {				/* default-B */
+		otg_ctrl |= OTG_ID;
+		if (isp->otg.state == OTG_STATE_A_IDLE
+				|| isp->otg.state == OTG_STATE_UNDEFINED) {
+			b_idle(isp, "init");
+			return;
+		}
+	}
+	OTG_CTRL_REG = otg_ctrl;
+}
+
+/* outputs from ISP1301_OTG_STATUS */
+static void update_otg2(struct isp1301 *isp, u8 otg_status)
+{
+	u32	otg_ctrl;
+
+	otg_ctrl = OTG_CTRL_REG
+			& OTG_CTRL_MASK
+			& ~OTG_XCEIV_INPUTS
+			& ~(OTG_BSESSVLD|OTG_BSESSEND);
+	if (otg_status & OTG_B_SESS_VLD)
+		otg_ctrl |= OTG_BSESSVLD;
+	else if (otg_status & OTG_B_SESS_END)
+		otg_ctrl |= OTG_BSESSEND;
+	OTG_CTRL_REG = otg_ctrl;
+}
+
+/* inputs going to ISP1301 */
+static void otg_update_isp(struct isp1301 *isp)
+{
+	u32	otg_ctrl, otg_change;
+	u8	set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP;
+
+	otg_ctrl = OTG_CTRL_REG;
+	otg_change = otg_ctrl ^ isp->last_otg_ctrl;
+	isp->last_otg_ctrl = otg_ctrl;
+	otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS;
+
+	switch (isp->otg.state) {
+	case OTG_STATE_B_IDLE:
+	case OTG_STATE_B_PERIPHERAL:
+	case OTG_STATE_B_SRP_INIT:
+		if (!(otg_ctrl & OTG_PULLUP)) {
+			// if (otg_ctrl & OTG_B_HNPEN) {
+			if (isp->otg.gadget->b_hnp_enable) {
+				isp->otg.state = OTG_STATE_B_WAIT_ACON;
+				pr_debug("  --> b_wait_acon\n");
+			}
+			goto pulldown;
+		}
+pullup:
+		set |= OTG1_DP_PULLUP;
+		clr |= OTG1_DP_PULLDOWN;
+		break;
+	case OTG_STATE_A_SUSPEND:
+	case OTG_STATE_A_PERIPHERAL:
+		if (otg_ctrl & OTG_PULLUP)
+			goto pullup;
+		/* FALLTHROUGH */
+	// case OTG_STATE_B_WAIT_ACON:
+	default:
+pulldown:
+		set |= OTG1_DP_PULLDOWN;
+		clr |= OTG1_DP_PULLUP;
+		break;
+	}
+
+#	define toggle(OTG,ISP) do { \
+		if (otg_ctrl & OTG) set |= ISP; \
+		else clr |= ISP; \
+		} while (0)
+
+	if (!(isp->otg.host))
+		otg_ctrl &= ~OTG_DRV_VBUS;
+
+	switch (isp->otg.state) {
+	case OTG_STATE_A_SUSPEND:
+		if (otg_ctrl & OTG_DRV_VBUS) {
+			set |= OTG1_VBUS_DRV;
+			break;
+		}
+		/* HNP failed for some reason (A_AIDL_BDIS timeout) */
+		notresponding(isp);
+
+		/* FALLTHROUGH */
+	case OTG_STATE_A_VBUS_ERR:
+		isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+		pr_debug("  --> a_wait_vfall\n");
+		/* FALLTHROUGH */
+	case OTG_STATE_A_WAIT_VFALL:
+		/* FIXME usbcore thinks port power is still on ... */
+		clr |= OTG1_VBUS_DRV;
+		break;
+	case OTG_STATE_A_IDLE:
+		if (otg_ctrl & OTG_DRV_VBUS) {
+			isp->otg.state = OTG_STATE_A_WAIT_VRISE;
+			pr_debug("  --> a_wait_vrise\n");
+		}
+		/* FALLTHROUGH */
+	default:
+		toggle(OTG_DRV_VBUS, OTG1_VBUS_DRV);
+	}
+
+	toggle(OTG_PU_VBUS, OTG1_VBUS_CHRG);
+	toggle(OTG_PD_VBUS, OTG1_VBUS_DISCHRG);
+
+#	undef toggle
+
+	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, set);
+	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, clr);
+
+	/* HNP switch to host or peripheral; and SRP */
+	if (otg_change & OTG_PULLUP) {
+		switch (isp->otg.state) {
+		case OTG_STATE_B_IDLE:
+			if (clr & OTG1_DP_PULLUP)
+				break;
+			isp->otg.state = OTG_STATE_B_PERIPHERAL;
+			pr_debug("  --> b_peripheral\n");
+			break;
+		case OTG_STATE_A_SUSPEND:
+			if (clr & OTG1_DP_PULLUP)
+				break;
+			isp->otg.state = OTG_STATE_A_PERIPHERAL;
+			pr_debug("  --> a_peripheral\n");
+			break;
+		default:
+			break;
+		}
+		OTG_CTRL_REG |= OTG_PULLUP;
+	}
+
+	check_state(isp, __FUNCTION__);
+	dump_regs(isp, "otg->isp1301");
+}
+
+static irqreturn_t omap_otg_irq(int irq, void *_isp, struct pt_regs *regs)
+{
+	u16		otg_irq = OTG_IRQ_SRC_REG;
+	u32		otg_ctrl;
+	int		ret = IRQ_NONE;
+	struct isp1301	*isp = _isp;
+
+	/* update ISP1301 transciever from OTG controller */
+	if (otg_irq & OPRT_CHG) {
+		OTG_IRQ_SRC_REG = OPRT_CHG;
+		isp1301_defer_work(isp, WORK_UPDATE_ISP);
+		ret = IRQ_HANDLED;
+
+	/* SRP to become b_peripheral failed */
+	} else if (otg_irq & B_SRP_TMROUT) {
+		pr_debug("otg: B_SRP_TIMEOUT, %06x\n", OTG_CTRL_REG);
+		notresponding(isp);
+
+		/* gadget drivers that care should monitor all kinds of
+		 * remote wakeup (SRP, normal) using their own timer
+		 * to give "check cable and A-device" messages.
+		 */
+		if (isp->otg.state == OTG_STATE_B_SRP_INIT)
+			b_idle(isp, "srp_timeout");
+
+		OTG_IRQ_SRC_REG = B_SRP_TMROUT;
+		ret = IRQ_HANDLED;
+
+	/* HNP to become b_host failed */
+	} else if (otg_irq & B_HNP_FAIL) {
+		pr_debug("otg: %s B_HNP_FAIL, %06x\n",
+				state_name(isp), OTG_CTRL_REG);
+		notresponding(isp);
+
+		otg_ctrl = OTG_CTRL_REG;
+		otg_ctrl |= OTG_BUSDROP;
+		otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+		OTG_CTRL_REG = otg_ctrl;
+
+		/* subset of b_peripheral()... */
+		isp->otg.state = OTG_STATE_B_PERIPHERAL;
+		pr_debug("  --> b_peripheral\n");
+
+		OTG_IRQ_SRC_REG = B_HNP_FAIL;
+		ret = IRQ_HANDLED;
+
+	/* detect SRP from B-device ... */
+	} else if (otg_irq & A_SRP_DETECT) {
+		pr_debug("otg: %s SRP_DETECT, %06x\n",
+				state_name(isp), OTG_CTRL_REG);
+
+		isp1301_defer_work(isp, WORK_UPDATE_OTG);
+		switch (isp->otg.state) {
+		case OTG_STATE_A_IDLE:
+			if (!isp->otg.host)
+				break;
+			isp1301_defer_work(isp, WORK_HOST_RESUME);
+			otg_ctrl = OTG_CTRL_REG;
+			otg_ctrl |= OTG_A_BUSREQ;
+			otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
+					& ~OTG_XCEIV_INPUTS
+					& OTG_CTRL_MASK;
+			OTG_CTRL_REG = otg_ctrl;
+			break;
+		default:
+			break;
+		}
+
+		OTG_IRQ_SRC_REG = A_SRP_DETECT;
+		ret = IRQ_HANDLED;
+
+	/* timer expired:  T(a_wait_bcon) and maybe T(a_wait_vrise)
+	 * we don't track them separately
+	 */
+	} else if (otg_irq & A_REQ_TMROUT) {
+		otg_ctrl = OTG_CTRL_REG;
+		pr_info("otg: BCON_TMOUT from %s, %06x\n",
+				state_name(isp), otg_ctrl);
+		notresponding(isp);
+
+		otg_ctrl |= OTG_BUSDROP;
+		otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+		OTG_CTRL_REG = otg_ctrl;
+		isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+
+		OTG_IRQ_SRC_REG = A_REQ_TMROUT;
+		ret = IRQ_HANDLED;
+
+	/* A-supplied voltage fell too low; overcurrent */
+	} else if (otg_irq & A_VBUS_ERR) {
+		otg_ctrl = OTG_CTRL_REG;
+		printk(KERN_ERR "otg: %s, VBUS_ERR %04x ctrl %06x\n",
+			state_name(isp), otg_irq, otg_ctrl);
+
+		otg_ctrl |= OTG_BUSDROP;
+		otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+		OTG_CTRL_REG = otg_ctrl;
+		isp->otg.state = OTG_STATE_A_VBUS_ERR;
+
+		OTG_IRQ_SRC_REG = A_VBUS_ERR;
+		ret = IRQ_HANDLED;
+
+	/* switch driver; the transciever code activates it,
+	 * ungating the udc clock or resuming OHCI.
+	 */
+	} else if (otg_irq & DRIVER_SWITCH) {
+		int	kick = 0;
+
+		otg_ctrl = OTG_CTRL_REG;
+		printk(KERN_NOTICE "otg: %s, SWITCH to %s, ctrl %06x\n",
+				state_name(isp),
+				(otg_ctrl & OTG_DRIVER_SEL)
+					? "gadget" : "host",
+				otg_ctrl);
+		isp1301_defer_work(isp, WORK_UPDATE_ISP);
+
+		/* role is peripheral */
+		if (otg_ctrl & OTG_DRIVER_SEL) {
+			switch (isp->otg.state) {
+			case OTG_STATE_A_IDLE:
+				b_idle(isp, __FUNCTION__);
+				break;
+			default:
+				break;
+			}
+			isp1301_defer_work(isp, WORK_UPDATE_ISP);
+
+		/* role is host */
+		} else {
+			if (!(otg_ctrl & OTG_ID)) {
+		 		otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
+				OTG_CTRL_REG = otg_ctrl | OTG_A_BUSREQ;
+			}
+
+			if (isp->otg.host) {
+				switch (isp->otg.state) {
+				case OTG_STATE_B_WAIT_ACON:
+					isp->otg.state = OTG_STATE_B_HOST;
+					pr_debug("  --> b_host\n");
+					kick = 1;
+					break;
+				case OTG_STATE_A_WAIT_BCON:
+					isp->otg.state = OTG_STATE_A_HOST;
+					pr_debug("  --> a_host\n");
+					break;
+				case OTG_STATE_A_PERIPHERAL:
+					isp->otg.state = OTG_STATE_A_WAIT_BCON;
+					pr_debug("  --> a_wait_bcon\n");
+					break;
+				default:
+					break;
+				}
+				isp1301_defer_work(isp, WORK_HOST_RESUME);
+			}
+		}
+
+		OTG_IRQ_SRC_REG = DRIVER_SWITCH;
+		ret = IRQ_HANDLED;
+
+		if (kick)
+			usb_bus_start_enum(isp->otg.host,
+						isp->otg.host->otg_port);
+	}
+
+	check_state(isp, __FUNCTION__);
+	return ret;
+}
+
+static struct platform_device *otg_dev;
+
+static int otg_init(struct isp1301 *isp)
+{
+	if (!otg_dev)
+		return -ENODEV;
+
+	dump_regs(isp, __FUNCTION__);
+	/* some of these values are board-specific... */
+	OTG_SYSCON_2_REG |= OTG_EN
+		/* for B-device: */
+		| SRP_GPDATA		/* 9msec Bdev D+ pulse */
+		| SRP_GPDVBUS		/* discharge after VBUS pulse */
+		// | (3 << 24)		/* 2msec VBUS pulse */
+		/* for A-device: */
+		| (0 << 20)		/* 200ms nominal A_WAIT_VRISE timer */
+		| SRP_DPW		/* detect 167+ns SRP pulses */
+		| SRP_DATA | SRP_VBUS	/* accept both kinds of SRP pulse */
+		;
+
+	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
+	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+
+	check_state(isp, __FUNCTION__);
+	pr_debug("otg: %s, %s %06x\n",
+			state_name(isp), __FUNCTION__, OTG_CTRL_REG);
+
+	OTG_IRQ_EN_REG = DRIVER_SWITCH | OPRT_CHG
+			| B_SRP_TMROUT | B_HNP_FAIL
+			| A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT;
+	OTG_SYSCON_2_REG |= OTG_EN;
+
+	return 0;
+}
+
+static int otg_probe(struct device *dev)
+{
+	// struct omap_usb_config *config = dev->platform_data;
+
+	otg_dev = to_platform_device(dev);
+	return 0;
+}
+
+static int otg_remove(struct device *dev)
+{
+	otg_dev = 0;
+	return 0;
+}
+
+struct device_driver omap_otg_driver = {
+	.name		= "omap_otg",
+	.bus		= &platform_bus_type,
+	.probe		= otg_probe,
+	.remove		= otg_remove,	
+};
+
+static int otg_bind(struct isp1301 *isp)
+{
+	int	status;
+
+	if (otg_dev)
+		return -EBUSY;
+
+	status = driver_register(&omap_otg_driver);
+	if (status < 0)
+		return status;
+
+	if (otg_dev)
+		status = request_irq(otg_dev->resource[1].start, omap_otg_irq,
+				SA_INTERRUPT, DRIVER_NAME, isp);
+	else
+		status = -ENODEV;
+
+	if (status < 0)
+		driver_unregister(&omap_otg_driver);
+	return status;
+}
+
+static void otg_unbind(struct isp1301 *isp)
+{
+	if (!otg_dev)
+		return;
+	free_irq(otg_dev->resource[1].start, isp);
+}
+
+#else
+
+/* OTG controller isn't clocked */
+
+#endif	/* CONFIG_USB_OTG */
+
+/*-------------------------------------------------------------------------*/
+
+static void b_peripheral(struct isp1301 *isp)
+{
+	enable_vbus_draw(isp, 8);
+	OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+	usb_gadget_vbus_connect(isp->otg.gadget);
+
+#ifdef	CONFIG_USB_OTG
+	otg_update_isp(isp);
+#else
+	/* UDC driver just set OTG_BSESSVLD */
+	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
+	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
+	isp->otg.state = OTG_STATE_B_PERIPHERAL;
+	pr_debug("  --> b_peripheral\n");
+	dump_regs(isp, "2periph");
+#endif
+}
+
+static int isp_update_otg(struct isp1301 *isp, u8 stat)
+{
+	u8			isp_stat, isp_bstat;
+	enum usb_otg_state	state = isp->otg.state;
+
+	if (stat & INTR_BDIS_ACON)
+		pr_debug("OTG:  BDIS_ACON, %s\n", state_name(isp));
+
+	/* start certain state transitions right away */
+	isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
+	if (isp_stat & INTR_ID_GND) {
+		if (isp->otg.default_a) {
+			switch (state) {
+			case OTG_STATE_B_IDLE:
+				a_idle(isp, "idle");
+				/* FALLTHROUGH */
+			case OTG_STATE_A_IDLE:
+				enable_vbus_source(isp);
+				/* FALLTHROUGH */
+			case OTG_STATE_A_WAIT_VRISE:
+				/* we skip over OTG_STATE_A_WAIT_BCON, since
+				 * the HC will transition to A_HOST (or
+				 * A_SUSPEND!) without our noticing except
+				 * when HNP is used.
+				 */
+				if (isp_stat & INTR_VBUS_VLD)
+					isp->otg.state = OTG_STATE_A_HOST;
+				break;
+			case OTG_STATE_A_WAIT_VFALL:
+				if (!(isp_stat & INTR_SESS_VLD))
+					a_idle(isp, "vfell");
+				break;
+			default:
+				if (!(isp_stat & INTR_VBUS_VLD))
+					isp->otg.state = OTG_STATE_A_VBUS_ERR;
+				break;
+			}
+			isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+		} else {
+			switch (state) {
+			case OTG_STATE_B_PERIPHERAL:
+			case OTG_STATE_B_HOST:
+			case OTG_STATE_B_WAIT_ACON:
+				usb_gadget_vbus_disconnect(isp->otg.gadget);
+				break;
+			default:
+				break;
+			}
+			if (state != OTG_STATE_A_IDLE)
+				a_idle(isp, "id");
+			if (isp->otg.host && state == OTG_STATE_A_IDLE)
+				isp1301_defer_work(isp, WORK_HOST_RESUME);
+			isp_bstat = 0;
+		}
+	} else {
+		/* if user unplugged mini-A end of cable,
+		 * don't bypass A_WAIT_VFALL.
+		 */
+		if (isp->otg.default_a) {
+			switch (state) {
+			default:
+				isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+				break;
+			case OTG_STATE_A_WAIT_VFALL:
+				state = OTG_STATE_A_IDLE;
+				/* khubd may take a while to notice and
+				 * handle this disconnect, so don't go
+				 * to B_IDLE quite yet.
+				 */
+				break;
+			case OTG_STATE_A_IDLE:
+				host_suspend(isp);
+				isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1,
+						MC1_BDIS_ACON_EN);
+				isp->otg.state = OTG_STATE_B_IDLE;
+				OTG_CTRL_REG &= OTG_CTRL_REG & OTG_CTRL_MASK
+						& ~OTG_CTRL_BITS;
+				break;
+			case OTG_STATE_B_IDLE:
+				break;
+			}
+		}
+		isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
+
+		switch (isp->otg.state) {
+		case OTG_STATE_B_PERIPHERAL:
+		case OTG_STATE_B_WAIT_ACON:
+		case OTG_STATE_B_HOST:
+			if (likely(isp_bstat & OTG_B_SESS_VLD))
+				break;
+			enable_vbus_draw(isp, 0);
+#ifndef	CONFIG_USB_OTG
+			/* UDC driver will clear OTG_BSESSVLD */
+			isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
+						OTG1_DP_PULLDOWN);
+			isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
+						OTG1_DP_PULLUP);
+			dump_regs(isp, __FUNCTION__);
+#endif
+			/* FALLTHROUGH */
+		case OTG_STATE_B_SRP_INIT:
+			b_idle(isp, __FUNCTION__);
+			OTG_CTRL_REG &= OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+			/* FALLTHROUGH */
+		case OTG_STATE_B_IDLE:
+			if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) {
+#ifdef	CONFIG_USB_OTG
+				update_otg1(isp, isp_stat);
+				update_otg2(isp, isp_bstat);
+#endif
+				b_peripheral(isp);
+			} else if (!(isp_stat & (INTR_VBUS_VLD|INTR_SESS_VLD)))
+				isp_bstat |= OTG_B_SESS_END;
+			break;
+		case OTG_STATE_A_WAIT_VFALL:
+			break;
+		default:
+			pr_debug("otg: unsupported b-device %s\n",
+				state_name(isp));
+			break;
+		}
+	}
+
+	if (state != isp->otg.state)
+		pr_debug("  isp, %s -> %s\n",
+				state_string(state), state_name(isp));
+
+#ifdef	CONFIG_USB_OTG
+	/* update the OTG controller state to match the isp1301; may
+	 * trigger OPRT_CHG irqs for changes going to the isp1301.
+	 */
+	update_otg1(isp, isp_stat);
+	update_otg2(isp, isp_bstat);
+	check_state(isp, __FUNCTION__);
+#endif
+
+	dump_regs(isp, "isp1301->otg");
+}
+
+/*-------------------------------------------------------------------------*/
+
+static u8 isp1301_clear_latch(struct isp1301 *isp)
+{
+	u8 latch = isp1301_get_u8(isp, ISP1301_INTERRUPT_LATCH);
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, latch);
+	return latch;
+}
+
+static void
+isp1301_work(void *data)
+{
+	struct isp1301	*isp = data;
+	int		stop;
+
+	/* implicit lock:  we're the only task using this device */
+	isp->working = 1;
+	do {
+		stop = test_bit(WORK_STOP, &isp->todo);
+
+#ifdef	CONFIG_USB_OTG
+		/* transfer state from otg engine to isp1301 */
+		if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) {
+			otg_update_isp(isp);
+			put_device(&isp->client.dev);
+		}
+#endif
+		/* transfer state from isp1301 to otg engine */
+		if (test_and_clear_bit(WORK_UPDATE_OTG, &isp->todo)) {
+			u8		stat = isp1301_clear_latch(isp);
+
+			isp_update_otg(isp, stat);
+			put_device(&isp->client.dev);
+		}
+
+		if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) {
+			u32	otg_ctrl;
+
+			/*
+			 * skip A_WAIT_VRISE; hc transitions invisibly
+			 * skip A_WAIT_BCON; same.
+			 */
+			switch (isp->otg.state) {
+			case OTG_STATE_A_WAIT_BCON:
+			case OTG_STATE_A_WAIT_VRISE:
+				isp->otg.state = OTG_STATE_A_HOST;
+				pr_debug("  --> a_host\n");
+				otg_ctrl = OTG_CTRL_REG;
+				otg_ctrl |= OTG_A_BUSREQ;
+				otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ)
+						& OTG_CTRL_MASK;
+				OTG_CTRL_REG = otg_ctrl;
+				break;
+			case OTG_STATE_B_WAIT_ACON:
+				isp->otg.state = OTG_STATE_B_HOST;
+				pr_debug("  --> b_host (acon)\n");
+				break;
+			case OTG_STATE_B_HOST:
+			case OTG_STATE_B_IDLE:
+			case OTG_STATE_A_IDLE:
+				break;
+			default:
+				pr_debug("  host resume in %s\n",
+						state_name(isp));
+			}
+			host_resume(isp);
+			// mdelay(10);
+			put_device(&isp->client.dev);
+		}
+
+		if (test_and_clear_bit(WORK_TIMER, &isp->todo)) {
+#ifdef	VERBOSE
+			dump_regs(isp, "timer");
+			if (!stop)
+				mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+#endif
+			put_device(&isp->client.dev);
+		}
+
+		if (isp->todo)
+			dev_vdbg(&isp->client.dev,
+				"work done, todo = 0x%lx\n",
+				isp->todo);
+		if (stop) {
+			dev_dbg(&isp->client.dev, "stop\n");
+			break;
+		}
+	} while (isp->todo);
+	isp->working = 0;
+}
+
+static irqreturn_t isp1301_irq(int irq, void *isp, struct pt_regs *regs)
+{
+	isp1301_defer_work(isp, WORK_UPDATE_OTG);
+	return IRQ_HANDLED;
+}
+
+static void isp1301_timer(unsigned long _isp)
+{
+	isp1301_defer_work((void *)_isp, WORK_TIMER);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void isp1301_release(struct device *dev)
+{
+	struct isp1301	*isp;
+
+	isp = container_of(dev, struct isp1301, client.dev);
+
+	/* ugly -- i2c hijacks our memory hook to wait_for_completion() */
+	if (isp->i2c_release)
+		isp->i2c_release(dev);
+	kfree (isp);
+}
+
+static struct isp1301 *the_transceiver;
+
+static int isp1301_detach_client(struct i2c_client *i2c)
+{
+	struct isp1301	*isp;
+
+	isp = container_of(i2c, struct isp1301, client);
+
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
+	free_irq(isp->irq, isp);
+#ifdef	CONFIG_USB_OTG
+	otg_unbind(isp);
+#endif
+	if (machine_is_omap_h2())
+		omap_free_gpio(2);
+
+	isp->timer.data = 0;
+	set_bit(WORK_STOP, &isp->todo);
+	del_timer_sync(&isp->timer);
+	flush_scheduled_work();
+
+	put_device(&i2c->dev);
+	the_transceiver = 0;
+
+	return i2c_detach_client(i2c);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* NOTE:  three modes are possible here, only one of which
+ * will be standards-conformant on any given system:
+ *
+ *  - OTG mode (dual-role), required if there's a Mini-AB connector
+ *  - HOST mode, for when there's one or more A (host) connectors
+ *  - DEVICE mode, for when there's a B/Mini-B (device) connector
+ *
+ * As a rule, you won't have an isp1301 chip unless it's there to
+ * support the OTG mode.  Other modes help testing USB controllers 
+ * in isolation from (full) OTG support, or maybe so later board
+ * revisions can help to support those feature.
+ */
+
+#ifdef	CONFIG_USB_OTG
+
+static int isp1301_otg_enable(struct isp1301 *isp)
+{
+	power_up(isp);
+	otg_init(isp);
+
+	/* NOTE:  since we don't change this, this provides
+	 * a few more interrupts than are strictly needed.
+	 */
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+	 	INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+	 	INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
+
+	dev_info(&isp->client.dev, "ready for dual-role USB ...\n");
+
+	return 0;
+}
+
+#endif
+
+/* add or disable the host device+driver */
+static int
+isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+	struct isp1301	*isp = container_of(otg, struct isp1301, otg);
+
+	if (!otg || isp != the_transceiver)
+		return -ENODEV;
+
+	if (!host) {
+		OTG_IRQ_EN_REG = 0;
+		power_down(isp);
+		isp->otg.host = 0;
+		return 0;
+	}
+
+#ifdef	CONFIG_USB_OTG
+	isp->otg.host = host;
+	dev_dbg(&isp->client.dev, "registered host\n");
+	host_suspend(isp);
+	if (isp->otg.gadget)
+		return isp1301_otg_enable(isp);
+	return 0;
+
+#elif	!defined(CONFIG_USB_GADGET_OMAP)
+	// FIXME update its refcount
+	isp->otg.host = host;
+
+	power_up(isp);
+
+	if (machine_is_omap_h2())
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+
+	dev_info(&isp->client.dev, "A-Host sessions ok\n");
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+	 	INTR_ID_GND);
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+	 	INTR_ID_GND);
+
+	/* If this has a Mini-AB connector, this mode is highly
+	 * nonstandard ... but can be handy for testing, especially with
+	 * the Mini-A end of an OTG cable.  (Or something nonstandard
+	 * like MiniB-to-StandardB, maybe built with a gender mender.)
+	 */
+	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);
+
+	dump_regs(isp, __FUNCTION__);
+
+	return 0;
+
+#else
+	dev_dbg(&isp->client.dev, "host sessions not allowed\n");
+	return -EINVAL;
+#endif
+
+}
+
+static int
+isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
+{
+	struct isp1301	*isp = container_of(otg, struct isp1301, otg);
+
+	if (!otg || isp != the_transceiver)
+		return -ENODEV;
+
+	if (!gadget) {
+		OTG_IRQ_EN_REG = 0;
+		if (!isp->otg.default_a)
+			enable_vbus_draw(isp, 0);
+		usb_gadget_vbus_disconnect(isp->otg.gadget);
+		isp->otg.gadget = 0;
+		power_down(isp);
+		return 0;
+	}
+
+#ifdef	CONFIG_USB_OTG
+	isp->otg.gadget = gadget;
+	dev_dbg(&isp->client.dev, "registered gadget\n");
+	/* gadget driver may be suspended until vbus_connect () */
+	if (isp->otg.host)
+		return isp1301_otg_enable(isp);
+	return 0;
+
+#elif	!defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE)
+	isp->otg.gadget = gadget;
+	// FIXME update its refcount
+
+	OTG_CTRL_REG = (OTG_CTRL_REG & OTG_CTRL_MASK
+				& ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS))
+			| OTG_ID;
+	power_up(isp);
+	isp->otg.state = OTG_STATE_B_IDLE;
+
+	if (machine_is_omap_h2())
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
+
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
+	 	INTR_SESS_VLD);
+	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+	 	INTR_VBUS_VLD);
+	dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
+	dump_regs(isp, __FUNCTION__);
+
+	/* If this has a Mini-AB connector, this mode is highly
+	 * nonstandard ... but can be handy for testing, so long
+	 * as you don't plug a Mini-A cable into the jack.
+	 */
+	if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD)
+		b_peripheral(isp);
+
+	return 0;
+
+#else
+	dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n");
+	return -EINVAL;
+#endif
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int
+isp1301_set_power(struct otg_transceiver *dev, unsigned mA)
+{
+	if (!the_transceiver)
+		return -ENODEV;
+	if (dev->state == OTG_STATE_B_PERIPHERAL)
+		enable_vbus_draw(the_transceiver, mA);
+	return 0;
+}
+
+static int
+isp1301_start_srp(struct otg_transceiver *dev)
+{
+	struct isp1301	*isp = container_of(dev, struct isp1301, otg);
+	u32		otg_ctrl;
+
+	if (!dev || isp != the_transceiver
+			|| isp->otg.state != OTG_STATE_B_IDLE)
+		return -ENODEV;
+
+	otg_ctrl = OTG_CTRL_REG;
+	if (!(otg_ctrl & OTG_BSESSEND))
+		return -EINVAL;
+
+	otg_ctrl |= OTG_B_BUSREQ;
+	otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK;
+	OTG_CTRL_REG = otg_ctrl;
+	isp->otg.state = OTG_STATE_B_SRP_INIT;
+
+	pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), OTG_CTRL_REG);
+#ifdef	CONFIG_USB_OTG
+	check_state(isp, __FUNCTION__);
+#endif
+	return 0;
+}
+
+static int
+isp1301_start_hnp(struct otg_transceiver *dev)
+{
+#ifdef	CONFIG_USB_OTG
+	struct isp1301	*isp = container_of(dev, struct isp1301, otg);
+
+	if (!dev || isp != the_transceiver)
+		return -ENODEV;
+	if (isp->otg.default_a && (isp->otg.host == NULL
+			|| !isp->otg.host->b_hnp_enable))
+		return -ENOTCONN;
+	if (!isp->otg.default_a && (isp->otg.gadget == NULL
+			|| !isp->otg.gadget->b_hnp_enable))
+		return -ENOTCONN;
+
+	/* We want hardware to manage most HNP protocol timings.
+	 * So do this part as early as possible...
+	 */
+	switch (isp->otg.state) {
+	case OTG_STATE_B_HOST:
+		isp->otg.state = OTG_STATE_B_PERIPHERAL;
+		/* caller will suspend next */
+		break;
+	case OTG_STATE_A_HOST:
+#if 0
+		/* autoconnect mode avoids irq latency bugs */
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
+				MC1_BDIS_ACON_EN);
+#endif
+		/* caller must suspend then clear A_BUSREQ */
+		usb_gadget_vbus_connect(isp->otg.gadget);
+		OTG_CTRL_REG |= OTG_A_SETB_HNPEN;
+
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		/* initiated by B-Host suspend */
+		break;
+	default:
+		return -EILSEQ;
+	}
+	pr_debug("otg: HNP %s, %06x ...\n",
+		state_name(isp), OTG_CTRL_REG);
+	check_state(isp, __FUNCTION__);
+	return 0;
+#else
+	/* srp-only */
+	return -EINVAL;
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* no error returns, they'd just make bus scanning stop */
+static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
+{
+	int			status;
+	struct isp1301		*isp;
+	struct i2c_client	*i2c;
+
+	if (the_transceiver)
+		return 0;
+
+	isp = kmalloc(sizeof *isp, GFP_KERNEL);
+	if (!isp)
+		return 0;
+
+	memset(isp, 0, sizeof *isp);
+
+	INIT_WORK(&isp->work, isp1301_work, isp);
+	init_timer(&isp->timer);
+	isp->timer.function = isp1301_timer;
+	isp->timer.data = (unsigned long) isp;
+
+	isp->irq = -1;
+	isp->client.addr = address;
+	i2c_set_clientdata(&isp->client, isp);
+	isp->client.adapter = bus;
+	isp->client.id = 1301;
+	isp->client.driver = &isp1301_driver;
+	strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE);
+	i2c = &isp->client;
+
+	/* if this is a true probe, verify the chip ... */
+	if (kind < 0) {
+		status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
+		if (status != I2C_VENDOR_ID_PHILIPS) {
+			dev_dbg(&bus->dev, "addr %d not philips id: %d\n",
+				address, status);
+			goto fail1;
+		}
+		status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
+		if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
+			dev_dbg(&bus->dev, "%d not isp1301, %d\n",
+				address, status);
+			goto fail1;
+		}
+	}
+
+	status = i2c_attach_client(i2c);
+	if (status < 0) {
+		dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
+				DRIVER_NAME, address, status);
+fail1:
+		kfree(isp);
+		return 0;
+	}
+	isp->i2c_release = i2c->dev.release;
+	i2c->dev.release = isp1301_release;
+
+	/* initial development used chiprev 2.00 */
+	status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE);
+	dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n",
+		status >> 8, status & 0xff);
+
+	/* make like power-on reset */
+	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK);
+
+	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI);
+	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI);
+
+	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
+				OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
+	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
+				~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
+
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0);
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
+	isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
+
+#ifdef	CONFIG_USB_OTG
+	status = otg_bind(isp);
+	if (status < 0) {
+		dev_dbg(&i2c->dev, "can't bind OTG\n");
+		goto fail2;
+	}
+#endif
+
+	if (machine_is_omap_h2()) {
+		/* full speed signaling by default */
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
+			MC1_SPEED_REG);
+		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
+			MC2_SPD_SUSP_CTRL);
+
+		/* IRQ wired at M14 */
+		omap_cfg_reg(M14_1510_GPIO2);
+		isp->irq = OMAP_GPIO_IRQ(2);
+		omap_request_gpio(2);
+		omap_set_gpio_direction(2, 1);
+		omap_set_gpio_edge_ctrl(2, OMAP_GPIO_FALLING_EDGE);
+	}
+
+	status = request_irq(isp->irq, isp1301_irq,
+			SA_SAMPLE_RANDOM, DRIVER_NAME, isp);
+	if (status < 0) {
+		dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
+				isp->irq, status);
+#ifdef	CONFIG_USB_OTG
+fail2:
+#endif
+		i2c_detach_client(i2c);
+		goto fail1;
+	}
+
+	isp->otg.dev = &isp->client.dev;
+	isp->otg.label = DRIVER_NAME;
+
+	isp->otg.set_host = isp1301_set_host,
+	isp->otg.set_peripheral = isp1301_set_peripheral,
+	isp->otg.set_power = isp1301_set_power,
+	isp->otg.start_srp = isp1301_start_srp,
+	isp->otg.start_hnp = isp1301_start_hnp,
+
+	enable_vbus_draw(isp, 0);
+	power_down(isp);
+	the_transceiver = isp;
+
+#ifdef	CONFIG_USB_OTG
+	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
+	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+#endif
+
+	dump_regs(isp, __FUNCTION__);
+
+#ifdef	VERBOSE
+	mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+	dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
+#endif
+
+	status = otg_set_transceiver(&isp->otg);
+	if (status < 0)
+		dev_err(&i2c->dev, "can't register transceiver, %d\n",
+			status);
+
+	return 0;
+}
+
+static int isp1301_scan_bus(struct i2c_adapter *bus)
+{
+	if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA
+			| I2C_FUNC_SMBUS_READ_WORD_DATA))
+		return -EINVAL;
+	return i2c_probe(bus, &addr_data, isp1301_probe);
+}
+
+static struct i2c_driver isp1301_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "isp1301_omap",
+	.id		= 1301,		/* FIXME "official", i2c-ids.h */
+	.class		= I2C_CLASS_HWMON,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= isp1301_scan_bus,
+	.detach_client	= isp1301_detach_client,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init isp_init(void)
+{
+	return i2c_add_driver(&isp1301_driver);
+}
+module_init(isp_init);
+
+static void __exit isp_exit(void)
+{
+	if (the_transceiver)
+		otg_set_transceiver(0);
+	i2c_del_driver(&isp1301_driver);
+}
+module_exit(isp_exit);
+
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c	2004-07-22 00:51:45 -07:00
+++ b/drivers/i2c/chips/it87.c	2004-08-12 13:00:13 -07:00
@@ -571,9 +571,9 @@
 	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 #define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_in0_ref)
+device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 /* This function is called when:
      * it87_driver is inserted (when this module is loaded), for each
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
--- a/drivers/i2c/chips/lm78.c	2004-07-12 17:17:36 -07:00
+++ b/drivers/i2c/chips/lm78.c	2004-08-12 13:00:12 -07:00
@@ -423,7 +423,7 @@
 	struct lm78_data *data = lm78_update_device(dev);
 	return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
 }
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
 /* Alarms */
 static ssize_t show_alarms(struct device *dev, char *buf)
@@ -615,7 +615,7 @@
 	device_create_file(&new_client->dev, &dev_attr_fan3_min);
 	device_create_file(&new_client->dev, &dev_attr_fan3_div);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_in0_ref);
+	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 
 	return 0;
 
diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
--- a/drivers/i2c/chips/lm85.c	2004-07-22 00:53:04 -07:00
+++ b/drivers/i2c/chips/lm85.c	2004-08-12 13:00:12 -07:00
@@ -465,7 +465,7 @@
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
 static ssize_t show_vrm_reg(struct device *dev, char *buf)
 {
@@ -874,7 +874,7 @@
 	device_create_file(&new_client->dev, &dev_attr_temp2_max);
 	device_create_file(&new_client->dev, &dev_attr_temp3_max);
 	device_create_file(&new_client->dev, &dev_attr_vrm);
-	device_create_file(&new_client->dev, &dev_attr_in0_ref);
+	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
 	return 0;
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c	2004-07-22 00:49:22 -07:00
+++ b/drivers/i2c/chips/w83627hf.c	2004-08-12 13:00:11 -07:00
@@ -635,9 +635,9 @@
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 #define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_in0_ref)
+device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 static ssize_t
 show_vrm_reg(struct device *dev, char *buf)
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	2004-07-22 00:49:22 -07:00
+++ b/drivers/i2c/chips/w83781d.c	2004-08-12 12:59:39 -07:00
@@ -503,9 +503,9 @@
 }
 
 static
-DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
+DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 #define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_in0_ref);
+device_create_file(&client->dev, &dev_attr_cpu0_vid);
 static ssize_t
 show_vrm_reg(struct device *dev, char *buf)
 {
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	2004-08-23 01:14:46 -07:00
+++ b/drivers/ide/ide-disk.c	2004-08-28 06:45:42 -07:00
@@ -1809,11 +1809,9 @@
 	if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
 		printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
 			drive->name, drive->head);
-		ide_cacheflush_p(drive);
-		ide_unregister_subdriver(drive);
-		DRIVER(drive)->busy--;
-		goto failed;
-	}
+		drive->attach = 0;
+	} else
+		drive->attach = 1;
 	DRIVER(drive)->busy--;
 	g->minors = 1 << PARTN_BITS;
 	strcpy(g->devfs_name, drive->devfs_name);
@@ -1821,7 +1819,6 @@
 	g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
 	set_capacity(g, current_capacity(drive));
 	g->fops = &idedisk_ops;
-	drive->attach = 1;
 	add_disk(g);
 	return 0;
 failed:
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	2004-08-23 01:14:46 -07:00
+++ b/drivers/ide/ide-probe.c	2004-08-28 06:47:33 -07:00
@@ -635,12 +635,11 @@
 	device_register(&hwif->gendev);
 }
 
-#ifdef CONFIG_PPC
 static int wait_hwif_ready(ide_hwif_t *hwif)
 {
 	int rc;
 
-	printk(KERN_INFO "Probing IDE interface %s...\n", hwif->name);
+	printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name);
 
 	/* Let HW settle down a bit from whatever init state we
 	 * come from */
@@ -671,7 +670,6 @@
 	
 	return rc;
 }
-#endif
 
 /*
  * This routine only knows how to look for drive units 0 and 1
@@ -717,7 +715,6 @@
 
 	local_irq_set(flags);
 
-#ifdef CONFIG_PPC
 	/* This is needed on some PPCs and a bunch of BIOS-less embedded
 	 * platforms. Typical cases are:
 	 * 
@@ -738,8 +735,7 @@
 	 *  BenH.
 	 */
 	if (wait_hwif_ready(hwif))
-		printk(KERN_WARNING "%s: Wait for ready failed before probe !\n", hwif->name);
-#endif /* CONFIG_PPC */
+		printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
 
 	/*
 	 * Second drive should only exist if first drive was found,
@@ -749,6 +745,18 @@
 		ide_drive_t *drive = &hwif->drives[unit];
 		drive->dn = (hwif->channel ? 2 : 0) + unit;
 		(void) probe_for_drive(drive);
+		if (drive->present && hwif->present && unit == 1) {
+			if (strcmp(hwif->drives[0].id->model, drive->id->model) == 0 &&
+			    /* Don't do this for noprobe or non ATA */
+			    strcmp(drive->id->model, "UNKNOWN") &&
+			    /* And beware of confused Maxtor drives that go "M0000000000"
+			      "The SN# is garbage in the ID block..." [Eric] */
+			    strncmp(drive->id->serial_no, "M0000000000000000000", 20) &&
+			    strncmp(hwif->drives[0].id->serial_no, drive->id->serial_no, 20) == 0) {
+				printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
+				drive->present = 0;
+			}
+		}
 		if (drive->present && !hwif->present) {
 			hwif->present = 1;
 			if (hwif->chipset != ide_4drives ||
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
--- a/drivers/ide/ide-tape.c	2004-08-12 17:03:53 -07:00
+++ b/drivers/ide/ide-tape.c	2004-08-28 04:22:52 -07:00
@@ -530,7 +530,6 @@
  */
 #define IDETAPE_DEBUG_INFO		0
 #define IDETAPE_DEBUG_LOG		0
-#define IDETAPE_DEBUG_LOG_VERBOSE	0
 #define IDETAPE_DEBUG_BUGS		1
 
 /*
@@ -1260,70 +1259,6 @@
  */
 static idetape_chrdev_t idetape_chrdevs[MAX_HWIFS * MAX_DRIVES];
 
-#if IDETAPE_DEBUG_LOG_VERBOSE
-
-/*
- * DO NOT REMOVE, BUILDING A VERBOSE DEBUG SCHEME FOR ATAPI
- */
-
-char *idetape_sense_key_verbose(u8 idetape_sense_key)
-{
-	switch (idetape_sense_key) {
-		default: {
-			char buf[22];
-			sprintf(buf, "IDETAPE_SENSE (0x%02x)", idetape_sense_key);
-			return(buf);
-		}
-
-	}
-}
-
-char *idetape_command_key_verbose(u8 idetape_command_key)
-{
-	switch (idetape_command_key) {
-		case IDETAPE_TEST_UNIT_READY_CMD:
-			return("TEST_UNIT_READY_CMD");
-		case IDETAPE_REWIND_CMD:
-			return("REWIND_CMD");
-		case IDETAPE_REQUEST_SENSE_CMD:
-			return("REQUEST_SENSE_CMD");
-		case IDETAPE_READ_CMD:
-			return("READ_CMD");
-		case IDETAPE_WRITE_CMD:
-			return("WRITE_CMD");
-		case IDETAPE_WRITE_FILEMARK_CMD:
-			return("WRITE_FILEMARK_CMD");
-		case IDETAPE_SPACE_CMD:
-			return("SPACE_CMD");
-		case IDETAPE_INQUIRY_CMD:
-			return("INQUIRY_CMD");
-		case IDETAPE_ERASE_CMD:
-			return("ERASE_CMD");
-		case IDETAPE_MODE_SENSE_CMD:
-			return("MODE_SENSE_CMD");
-		case IDETAPE_MODE_SELECT_CMD:
-			return("MODE_SELECT_CMD");
-		case IDETAPE_LOAD_UNLOAD_CMD:
-			return("LOAD_UNLOAD_CMD");
-		case IDETAPE_PREVENT_CMD:
-			return("PREVENT_CMD");
-		case IDETAPE_LOCATE_CMD:
-			return("LOCATE_CMD");
-		case IDETAPE_READ_POSITION_CMD:
-			return("READ_POSITION_CMD");
-		case IDETAPE_READ_BUFFER_CMD:
-			return("READ_BUFFER_CMD");
-		case IDETAPE_SET_SPEED_CMD:
-			return("SET_SPEED_CMD");
-		default: {
-				char buf[20];
-				sprintf(buf, "CMD (0x%02x)", idetape_command_key);
-				return(buf);
-			}
-	}
-}
-#endif /* IDETAPE_DEBUG_LOG_VERBOSE */
-
 /*
  *      Function declarations
  *
@@ -1507,15 +1442,6 @@
 			"asc = %x, ascq = %x\n",
 			pc->c[0], result->sense_key,
 			result->asc, result->ascq);
-#if IDETAPE_DEBUG_LOG_VERBOSE
-	if (tape->debug_level >= 1)
-		printk(KERN_INFO "ide-tape: pc = %s, sense key = %x, "
-			"asc = %x, ascq = %x\n",
-			idetape_command_key_verbose((byte) pc->c[0]),
-			result->sense_key,
-			result->asc,
-			result->ascq);
-#endif /* IDETAPE_DEBUG_LOG_VERBOSE */
 #endif /* IDETAPE_DEBUG_LOG */
 
 	/*
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	2004-08-23 17:58:03 -07:00
+++ b/drivers/ide/ide.c	2004-08-28 04:08:30 -07:00
@@ -1348,23 +1348,6 @@
 	return err;
 }
 
-int ide_atapi_to_scsi (ide_drive_t *drive, int arg)
-{
-	if (drive->media == ide_disk) {
-		drive->scsi = 0;
-		return 0;
-	}
-
-	if (DRIVER(drive)->cleanup(drive)) {
-		drive->scsi = 0;
-		return 0;
-	}
-
-	drive->scsi = (u8) arg;
-	ata_attach(drive);
-	return 0;
-}
-
 void ide_add_generic_settings (ide_drive_t *drive)
 {
 /*
@@ -1379,8 +1362,6 @@
 	ide_add_setting(drive,	"init_speed",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	70,				1,		1,		&drive->init_speed,		NULL);
 	ide_add_setting(drive,	"current_speed",	SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	70,				1,		1,		&drive->current_speed,		set_xfer_rate);
 	ide_add_setting(drive,	"number",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	3,				1,		1,		&drive->dn,			NULL);
-	if (drive->media != ide_disk)
-		ide_add_setting(drive,	"ide-scsi",		SETTING_RW,					-1,		HDIO_SET_IDE_SCSI,		TYPE_BYTE,	0,	1,				1,		1,		&drive->scsi,			ide_atapi_to_scsi);
 }
 
 int system_bus_clock (void)
diff -Nru a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
--- a/drivers/ide/legacy/Makefile	2004-02-01 10:19:06 -08:00
+++ b/drivers/ide/legacy/Makefile	2004-08-28 08:30:35 -07:00
@@ -10,6 +10,5 @@
 
 # Last of all
 obj-$(CONFIG_BLK_DEV_HD)		+= hd.o
-obj-$(CONFIG_BLK_DEV_HD98)		+= hd98.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
diff -Nru a/drivers/ide/legacy/pdc4030.c b/drivers/ide/legacy/pdc4030.c
--- a/drivers/ide/legacy/pdc4030.c	2004-06-23 16:08:35 -07:00
+++ b/drivers/ide/legacy/pdc4030.c	2004-08-28 08:35:05 -07:00
@@ -354,15 +354,6 @@
 			  (unsigned long)rq->nr_sectors - nsect);
 #endif /* DEBUG_READ */
 
-#ifdef CONFIG_IDE_TASKFILE_IO
-	task_bio_sectors(drive, rq, nsect, IDE_PIO_IN);
-
-	/* FIXME: can we check status after transfer on pdc4030? */
-	/* Complete previously submitted bios. */
-	while (rq->bio != rq->cbio)
-		if (!DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio)))
-			return ide_stopped;
-#else /* CONFIG_IDE_TASKFILE_IO */
 	HWIF(drive)->ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
 	rq->buffer += nsect<<9;
 	rq->sector += nsect;
@@ -370,7 +361,6 @@
 	rq->nr_sectors -= nsect;
 	if (!rq->current_nr_sectors)
 		DRIVER(drive)->end_request(drive, 1, 0);
-#endif /* CONFIG_IDE_TASKFILE_IO */
 
 /*
  * Now the data has been read in, do the following:
@@ -421,12 +411,8 @@
 static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-#ifdef CONFIG_IDE_TASKFILE_IO
-	struct request *rq = hwgroup->rq;
-#else
 	struct request *rq = &hwgroup->wrq;
 	struct bio *bio = rq->bio;
-#endif
 
 	if ((HWIF(drive)->INB(IDE_STATUS_REG)) & BUSY_STAT) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -450,15 +436,10 @@
 	printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
 #endif /* DEBUG_WRITE */
 
-#ifdef CONFIG_IDE_TASKFILE_IO
-	/* Complete previously submitted bios. */
-	while (rq->bio != rq->cbio)
-		(void) DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio));
-#else
 	bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments;
 	rq = hwgroup->rq;
 	DRIVER(drive)->end_request(drive, 1, rq->hard_nr_sectors);
-#endif
+
 	return ide_stopped;
 }
 
@@ -466,27 +447,6 @@
  * promise_multwrite() transfers a block of up to mcount sectors of data
  * to a drive as part of a disk multiple-sector write operation.
  */
-#ifdef CONFIG_IDE_TASKFILE_IO
-static void promise_multwrite (ide_drive_t *drive, unsigned int msect)
-{
-	struct request* rq = HWGROUP(drive)->rq;
-	unsigned int nsect;
-
-	rq->errors = 0;
-	do {
-		nsect = rq->current_nr_sectors;
-		if (nsect > msect)
-			nsect = msect;
-
-		task_bio_sectors(drive, rq, nsect, IDE_PIO_OUT);
-
-		if (!rq->nr_sectors)
-			msect = 0;
-		else
-			msect -= nsect;
-	} while (msect);
-}
-#else /* CONFIG_IDE_TASKFILE_IO */
 static void promise_multwrite (ide_drive_t *drive, unsigned int mcount)
 {
 	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
@@ -537,7 +497,6 @@
 		taskfile_output_data(drive, buffer, nsect<<7);
 	} while (mcount);
 }
-#endif
 
 /*
  * promise_write_pollfunc() is the handler for disk write completion polling.
@@ -545,12 +504,8 @@
 static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-#ifdef CONFIG_IDE_TASKFILE_IO
-	struct request *rq = hwgroup->rq;
-#else
 	struct request *rq = &hwgroup->wrq;
 	struct bio *bio = rq->bio;
-#endif
 
 	if (HWIF(drive)->INB(IDE_NSECTOR_REG) != 0) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -564,19 +519,11 @@
 		}
 		hwgroup->poll_timeout = 0;
 		printk(KERN_ERR "%s: write timed-out!\n",drive->name);
-#ifndef CONFIG_IDE_TASKFILE_IO
 		bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments;
-#endif
 		return DRIVER(drive)->error(drive, "write timeout",
 				HWIF(drive)->INB(IDE_STATUS_REG));
 	}
 
-#ifdef CONFIG_IDE_TASKFILE_IO
-	/* Complete previously submitted bios. */
-	while (rq->bio != rq->cbio)
-		(void) DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio));
-#endif
-
 	/*
 	 * Now write out last 4 sectors and poll for not BUSY
 	 */
@@ -602,11 +549,7 @@
 static ide_startstop_t promise_write (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-#ifdef CONFIG_IDE_TASKFILE_IO
-	struct request *rq = hwgroup->rq;
-#else
 	struct request *rq = &hwgroup->wrq;
-#endif
 
 #ifdef DEBUG_WRITE
 	printk(KERN_DEBUG "%s: %s: sectors(%lu-%lu)\n",
@@ -654,39 +597,14 @@
  * already set up. It issues a READ or WRITE command to the Promise
  * controller, assuming LBA has been used to set up the block number.
  */
-#ifndef CONFIG_IDE_TASKFILE_IO
 ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
 {
 	ide_startstop_t startstop;
 	unsigned long timeout;
 	u8 stat = 0;
-#else
-static ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
-{
-	struct request *rq	= HWGROUP(drive)->rq;
-	task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
-	ide_startstop_t startstop;
-	unsigned long timeout;
-	u8 stat = 0;
-
-	if (IDE_CONTROL_REG)
-		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);	/* clear nIEN */
-	SELECT_MASK(drive, 0);
-	HWIF(drive)->OUTB(taskfile->feature, IDE_FEATURE_REG);
-	HWIF(drive)->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
-	/* refers to number of sectors to transfer */
-	HWIF(drive)->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
-	/* refers to sector offset or start sector */
-	HWIF(drive)->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
-	HWIF(drive)->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
-	HWIF(drive)->OUTB(taskfile->device_head, IDE_SELECT_REG);
-	HWIF(drive)->OUTB(taskfile->command, IDE_COMMAND_REG);
-#endif
 
 	if (rq_data_dir(rq) == READ) {
-#ifndef CONFIG_IDE_TASKFILE_IO
 		HWIF(drive)->OUTB(PROMISE_READ, IDE_COMMAND_REG);
-#endif
 /*
  * The card's behaviour is odd at this point. If the data is
  * available, DRQ will be true, and no interrupt will be
@@ -722,9 +640,7 @@
 				"waiting - Odd!\n", drive->name);
 		return ide_stopped;
 	} else {
-#ifndef CONFIG_IDE_TASKFILE_IO
 		HWIF(drive)->OUTB(PROMISE_WRITE, IDE_COMMAND_REG);
-#endif
 		if (ide_wait_stat(&startstop, drive, DATA_READY,
 				drive->bad_wstat, WAIT_DRQ)) {
 			printk(KERN_ERR "%s: no DRQ after issuing "
@@ -733,9 +649,7 @@
 	    	}
 		if (!drive->unmask)
 			local_irq_disable();
-#ifndef CONFIG_IDE_TASKFILE_IO
 		HWGROUP(drive)->wrq = *rq; /* scratchpad */
-#endif
 		return promise_write(drive);
 	}
 }
@@ -749,14 +663,9 @@
 	*/
 	ide_hwif_t *hwif = HWIF(drive);
 	int drive_number = (hwif->channel << 1) + drive->select.b.unit;
-#ifdef CONFIG_IDE_TASKFILE_IO
-	struct hd_drive_task_hdr taskfile;
-	ide_task_t args;
-#endif
 
 	BUG_ON(rq->nr_sectors > 127);
 
-#ifndef CONFIG_IDE_TASKFILE_IO
 	if (IDE_CONTROL_REG)
 		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
 	hwif->OUTB(drive_number, IDE_FEATURE_REG);
@@ -767,27 +676,4 @@
 	hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
 
 	return do_pdc4030_io(drive, rq);
-#else /* !CONFIG_IDE_TASKFILE_IO */
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-
-	taskfile.feature	= drive_number;
-	taskfile.sector_count	= rq->nr_sectors;
-	taskfile.sector_number	= block;
-	taskfile.low_cylinder	= (block>>=8);
-	taskfile.high_cylinder	= (block>>=8);
-	taskfile.device_head	= ((block>>8)&0x0f)|drive->select.all;
-	taskfile.command	= (rq->cmd==READ)?PROMISE_READ:PROMISE_WRITE;
-
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memset(args.hobRegister, 0, sizeof(struct hd_drive_hob_hdr));
-	/*
-	 * Setup the bits of args that we do need.
-	 * Note that we don't use the generic interrupt handlers.
-	 */
-	args.handler		= NULL;
-	args.rq			= (struct request *) rq;
-	rq->special		= (ide_task_t *)&args;
-
-	return do_pdc4030_io(drive, &args);
-#endif /* !CONFIG_IDE_TASKFILE_IO */
 }
diff -Nru a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
--- a/drivers/ide/legacy/qd65xx.h	2003-02-17 10:55:15 -08:00
+++ b/drivers/ide/legacy/qd65xx.h	2004-08-25 18:52:19 -07:00
@@ -47,10 +47,10 @@
 /* Drive specific timing taken from DOS driver v3.7 */
 
 struct qd65xx_timing_s {
-	char	offset;   /* ofset from the beginning of Model Number" */
+	s8	offset;   /* ofset from the beginning of Model Number" */
 	char	model[4];    /* 4 chars from Model number, no conversion */
-	short	active;   /* active time */
-	short	recovery; /* recovery time */
+	s16	active;   /* active time */
+	s16	recovery; /* recovery time */
 } qd65xx_timing [] = {
 	{ 30, "2040", 110, 225 },  /* Conner CP30204			*/
 	{ 30, "2045", 135, 225 },  /* Conner CP30254			*/
diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
--- a/drivers/ide/pci/cs5520.c	2004-08-09 09:59:19 -07:00
+++ b/drivers/ide/pci/cs5520.c	2004-08-28 08:27:45 -07:00
@@ -290,7 +290,10 @@
 		return 1;
 	}
 	pci_set_master(dev);
-	pci_set_dma_mask(dev, 0xFFFFFFFF);
+	if (pci_set_dma_mask(dev, 0xFFFFFFFF)) {
+		printk(KERN_WARNING "cs5520: No suitable DMA available.\n");
+		return -ENODEV;
+	}
 	init_chipset_cs5520(dev, d->name);
 
 	index.all = 0xf0f0;
diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
--- a/drivers/input/serio/Kconfig	2004-06-17 23:43:53 -07:00
+++ b/drivers/input/serio/Kconfig	2004-08-27 13:05:05 -07:00
@@ -20,7 +20,7 @@
 	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
 	default y
 	select SERIO
-	depends on !PARISC
+	depends on !PARISC && (!ARM || ARCH_SHARK || ARCH_EBSA285)
 	---help---
 	  i8042 is the chip over which the standard AT keyboard and PS/2
 	  mouse are connected to the computer. If you use these devices,
diff -Nru a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
--- a/drivers/input/serio/gscps2.c	2004-05-09 18:23:19 -07:00
+++ b/drivers/input/serio/gscps2.c	2004-08-24 02:09:07 -07:00
@@ -6,7 +6,7 @@
  * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
  *
  * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
- * 	Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
+ * 	Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
  *	Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
  *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
  *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
diff -Nru a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
--- a/drivers/isdn/capi/capidrv.c	2004-07-13 06:46:53 -07:00
+++ b/drivers/isdn/capi/capidrv.c	2004-08-27 12:27:24 -07:00
@@ -512,7 +512,8 @@
 	len = CAPIMSG_LEN(cmsg->buf);
 	skb = alloc_skb(len, GFP_ATOMIC);
 	memcpy(skb_put(skb, len), cmsg->buf, len);
-	capi20_put_message(&global.ap, skb);
+	if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR)
+		kfree_skb(skb);
 }
 
 /* -------- state machine -------------------------------------------- */
diff -Nru a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
--- a/drivers/isdn/hardware/avm/b1.c	2004-07-30 08:31:13 -07:00
+++ b/drivers/isdn/hardware/avm/b1.c	2004-08-27 12:51:03 -07:00
@@ -389,7 +389,7 @@
 					     CAPIMSG_NCCI(skb->data),
 					     CAPIMSG_MSGID(skb->data));
 		if (retval != CAPI_NOERROR) 
-			goto out;
+			return retval;
 
 		dlen = CAPIMSG_DATALEN(skb->data);
 
@@ -399,16 +399,14 @@
 		b1_put_slice(port, skb->data + len, dlen);
 		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
-		retval = CAPI_NOERROR;
-
 	 	spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_MESSAGE);
 		b1_put_slice(port, skb->data, len);
 		spin_unlock_irqrestore(&card->lock, flags);
 	}
- out:
+
 	dev_kfree_skb_any(skb);
-	return retval;
+	return CAPI_NOERROR;
 }
 
 /* ------------------------------------------------------------- */
diff -Nru a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
--- a/drivers/isdn/hardware/avm/b1dma.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hardware/avm/b1dma.c	2004-08-27 12:51:03 -07:00
@@ -839,8 +839,6 @@
 	}
 	if (retval == CAPI_NOERROR) 
 		b1dma_queue_tx(card, skb);
-	else
-		dev_kfree_skb_any(skb);
 
 	return retval;
 }
diff -Nru a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
--- a/drivers/isdn/hardware/avm/c4.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hardware/avm/c4.c	2004-08-27 12:51:03 -07:00
@@ -1029,8 +1029,6 @@
 		spin_lock_irqsave(&card->lock, flags);
 		c4_dispatch_tx(card);
 		spin_unlock_irqrestore(&card->lock, flags);
-	} else {
-		dev_kfree_skb_any(skb);
 	}
 	return retval;
 }
diff -Nru a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
--- a/drivers/isdn/hardware/avm/t1isa.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hardware/avm/t1isa.c	2004-08-27 12:51:03 -07:00
@@ -472,7 +472,7 @@
 					     CAPIMSG_NCCI(skb->data),
 					     CAPIMSG_MSGID(skb->data));
 		if (retval != CAPI_NOERROR) 
-			goto out;
+			return retval;
 
 		dlen = CAPIMSG_DATALEN(skb->data);
 
@@ -482,16 +482,15 @@
 		t1_put_slice(port, skb->data + len, dlen);
 		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
-		retval = CAPI_NOERROR;
 
 		spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_MESSAGE);
 		t1_put_slice(port, skb->data, len);
 		spin_unlock_irqrestore(&card->lock, flags);
 	}
- out:
+
 	dev_kfree_skb_any(skb);
-	return retval;
+	return CAPI_NOERROR;
 }
 /* ------------------------------------------------------------- */
 
diff -Nru a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
--- a/drivers/isdn/hardware/eicon/capifunc.c	2004-07-12 01:01:03 -07:00
+++ b/drivers/isdn/hardware/eicon/capifunc.c	2004-08-27 12:57:40 -07:00
@@ -1,4 +1,4 @@
-/* $Id: capifunc.c,v 1.61.4.2 2004/05/05 16:09:25 armin Exp $
+/* $Id: capifunc.c,v 1.61.4.5 2004/08/27 20:10:12 armin Exp $
  *
  * ISDN interface module for Eicon active cards DIVA.
  * CAPI Interface common functions
@@ -998,7 +998,8 @@
 
       write_end:
 	diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
-	diva_os_free_message_buffer(dmb);
+	if (retval == CAPI_NOERROR)
+		diva_os_free_message_buffer(dmb);
 	return retval;
 }
 
diff -Nru a/drivers/isdn/hardware/eicon/capifunc.h b/drivers/isdn/hardware/eicon/capifunc.h
--- a/drivers/isdn/hardware/eicon/capifunc.h	2004-03-20 10:18:26 -08:00
+++ b/drivers/isdn/hardware/eicon/capifunc.h	2004-08-28 13:14:28 -07:00
@@ -1,4 +1,4 @@
-/* $Id: capifunc.h,v 1.11 2004/03/20 17:19:58 armin Exp $
+/* $Id: capifunc.h,v 1.11.4.1 2004/08/28 20:03:53 armin Exp $
  *
  * ISDN interface module for Eicon active cards DIVA.
  * CAPI Interface common functions
@@ -12,8 +12,6 @@
 
 #ifndef __CAPIFUNC_H__
 #define __CAPIFUNC_H__
-
-#define MAX_DESCRIPTORS  32
 
 #define DRRELMAJOR  2
 #define DRRELMINOR  0
diff -Nru a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
--- a/drivers/isdn/hardware/eicon/debug.c	2004-07-12 01:01:03 -07:00
+++ b/drivers/isdn/hardware/eicon/debug.c	2004-08-28 13:14:29 -07:00
@@ -5,6 +5,7 @@
 #include "divasync.h"
 #include "kst_ifc.h"
 #include "maintidi.h"
+#include "man_defs.h"
 
 /*
   LOCALS
@@ -13,17 +14,23 @@
 
 static void DI_register (void *arg);
 static void DI_deregister (pDbgHandle hDbg);
-static void DI_format (int do_lock, word id, int type, char *format, va_list ap);
+static void DI_format (int do_lock, word id, int type, char *format, va_list argument_list);
 static void DI_format_locked   (word id, int type, char *format, va_list argument_list);
 static void DI_format_old (word id, char *format, va_list ap) { }
-static void DiProcessEventLog (word id, dword msgID, va_list ap) { }
+static void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap) { }
 static void single_p (byte * P, word * PLength, byte Id);
 static void diva_maint_xdi_cb (ENTITY* e);
 static word SuperTraceCreateReadReq (byte* P, const char* path);
+static int diva_mnt_cmp_nmbr (const char* nmbr);
+static void diva_free_dma_descriptor (IDI_CALL request, int nr);
+static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic);
 void diva_mnt_internal_dprintf (dword drv_id, dword type, char* p, ...);
 
 static dword MaxDumpSize = 256 ;
 static dword MaxXlogSize = 2 + 128 ;
+static char  TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH+1];
+static int TraceFilterIdent   = -1;
+static int TraceFilterChannel = -1;
 
 typedef struct _diva_maint_client {
   dword       sec;
@@ -40,9 +47,10 @@
   BUFFERS     XData;
   char        xbuffer[2048+512];
   byte*       pmem;
-	int         request_pending;
+  int         request_pending;
+  int         dma_handle;
 } diva_maint_client_t;
-static diva_maint_client_t clients[64];
+static diva_maint_client_t clients[MAX_DESCRIPTORS];
 
 static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask);
 
@@ -201,6 +209,10 @@
     return (-1);
   }
 
+  TraceFilter[0]     =  0;
+  TraceFilterIdent   = -1;
+  TraceFilterChannel = -1;
+
   dbg_base = base;
 
   diva_os_get_time (&start_sec, &start_usec);
@@ -249,7 +261,6 @@
 		return (-1);
   }
 
-
   return (0);
 }
 
@@ -302,16 +313,16 @@
                                                diva_os_spin_lock_magic_t* old_irql) {
   diva_dbg_entry_head_t*     pmsg = NULL;
 
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, old_irql, "read");
+  diva_os_enter_spin_lock (&dbg_q_lock, old_irql, "read");
   if (dbg_q_busy) {
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_busy");
+    diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_busy");
     return NULL;
   }
   dbg_q_busy = 1;
 
   if (!(pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, size))) {
     dbg_q_busy = 0;
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_empty");
+    diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_empty");
   }
 
   return (pmsg);
@@ -330,7 +341,7 @@
 		queueFreeMsg (dbg_queue);
 	}
 	dbg_q_busy = 0;
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_ack");
+  diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_ack");
 }
 
 
@@ -378,14 +389,14 @@
 		return ;
   }
 
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 
   for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
     if (clients[id].hDbg == hDbg) {
       /*
         driver already registered
         */
-      diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+      diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
       return;
     }
     if (clients[id].hDbg) { /* slot is busy */
@@ -468,7 +479,7 @@
     }
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
 }
 
 static void DI_deregister (pDbgHandle hDbg) {
@@ -480,8 +491,8 @@
 
   diva_os_get_time (&sec, &usec);
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "read");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
 
   for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
     if (clients[i].hDbg == hDbg) {
@@ -543,8 +554,8 @@
     }
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "read_ack");
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read_ack");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack");
 
   if (pmem) {
     diva_os_free (0, pmem);
@@ -562,7 +573,7 @@
                        unsigned short id,
                        int type,
                        char *format,
-                       va_list ap) {
+                       va_list argument_list) {
   diva_os_spin_lock_magic_t old_irql;
   dword sec, usec;
   diva_dbg_entry_head_t* pmsg = NULL;
@@ -571,14 +582,26 @@
   static char fmtBuf[MSG_FRAME_MAX_SIZE+sizeof(*pmsg)+1];
   char          *data;
   unsigned short code;
+  va_list ap;
 
-  if (!format)
+  if (diva_os_in_irq()) {
+    dbg_sequence++;
     return;
+  }
+
+	if ((!format) ||
+			((TraceFilter[0] != 0) && ((TraceFilterIdent < 0) || (TraceFilterChannel < 0)))) {
+		return;
+	}
+
+
   
+  ap = argument_list;
+
   diva_os_get_time (&sec, &usec);
 
   if (do_lock) {
-    diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "format");
+    diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "format");
   }
 
   switch (type) {
@@ -703,7 +726,7 @@
   }
 
   if (do_lock) {
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "format");
+    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "format");
   }
 }
 
@@ -720,7 +743,7 @@
     return (-1);
   }
 
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info");
 
   if (clients[id].hDbg) {
     *p++ = 1;
@@ -757,7 +780,7 @@
   }
   *p++ = 0;
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info");
 
   return (p - data);
 }
@@ -769,7 +792,7 @@
   if (!data || !id || (id >= (sizeof(clients)/sizeof(clients[0])))) {
     return (-1);
   }
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info");
 
   if (clients[id].hDbg) {
     ret = 4;
@@ -779,7 +802,7 @@
     *data++= (byte)(clients[id].hDbg->dbgMask >> 24);
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info");
 
   return (ret);
 }
@@ -793,8 +816,8 @@
     return (-1);
   }
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "dbg mask");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "dbg mask");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "dbg mask");
 
   if (clients[id].hDbg) {
     dword old_mask = clients[id].hDbg->dbgMask;
@@ -806,14 +829,14 @@
   }
 
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "dbg mask");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "dbg mask");
 
   if (clients[id].request_pending) {
     clients[id].request_pending = 0;
     (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "dbg mask");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
 
   return (ret);
 }
@@ -851,12 +874,12 @@
   diva_os_get_time (&sec, &usec);
   diva_get_idi_adapter_info (d->request, &serial, &logical);
   if (serial & 0xff000000) {
-    sprintf (tmp, "ADAPTER:%d SN:%d-%d",
+    sprintf (tmp, "ADAPTER:%d SN:%u-%d",
              (int)logical,
              serial & 0x00ffffff,
              (byte)(((serial & 0xff000000) >> 24) + 1));
   } else {
-    sprintf (tmp, "ADAPTER:%d SN:%d", (int)logical, serial);
+    sprintf (tmp, "ADAPTER:%d SN:%u", (int)logical, serial);
   }
 
   if (!(pmem = diva_os_malloc (0, DivaSTraceGetMemotyRequirement (d->channels)))) {
@@ -864,13 +887,13 @@
   }
   memset (pmem, 0x00, DivaSTraceGetMemotyRequirement (d->channels));
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 
   for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
     if (clients[id].hDbg && (clients[id].request == d->request)) {
-      diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
-      diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
+      diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
+      diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
       return;
     }
     if (clients[id].hDbg) { /* slot is busy */
@@ -891,8 +914,8 @@
   }
 
   if (free_id < 0) {
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
-    diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
+    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
+    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
     diva_os_free (0, pmem);
     return;
   }
@@ -908,6 +931,7 @@
   clients[id].Dbg.drvTag[0] = 0;
   clients[id].logical  = (int)logical;
   clients[id].channels = (int)d->channels;
+  clients[id].dma_handle = -1;
 
   clients[id].Dbg.dbgMask    = 0;
   clients[id].dbgMask        = clients[id].Dbg.dbgMask;
@@ -949,8 +973,8 @@
     clients[id].request = NULL;
     clients[id].request_pending = 0;
     clients[id].hDbg    = NULL;
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
-    diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
+    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
+    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
     diva_os_free (0, pmem);
     return;
   }
@@ -988,14 +1012,14 @@
   org_mask = clients[id].Dbg.dbgMask;
   clients[id].Dbg.dbgMask = 0;
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
 
   if (clients[id].request_pending) {
     clients[id].request_pending = 0;
     (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
 
 	diva_set_driver_dbg_mask (id, org_mask);
 }
@@ -1012,8 +1036,8 @@
 
   diva_os_get_time (&sec, &usec);
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "read");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
 
   for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
     if (clients[i].hDbg && (clients[i].request == d->request)) {
@@ -1030,8 +1054,15 @@
       }
 
       clients[i].hDbg    = NULL;
-      clients[i].request = NULL;
       clients[i].request_pending = 0;
+      if (clients[i].dma_handle >= 0) {
+        /*
+          Free DMA handle
+          */
+        diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
+        clients[i].dma_handle = -1;
+      }
+      clients[i].request = NULL;
 
       /*
         Log driver register, MAINT driver ID is '0'
@@ -1069,8 +1100,8 @@
     }
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "read_ack");
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read_ack");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack");
 
   if (pmem) {
     diva_os_free (0, pmem);
@@ -1142,6 +1173,42 @@
 
   if (pC && pC->pIdiLib && pC->request) {
     ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
+    IDI_SYNC_REQ* preq;
+    char buffer[((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
+    char features[4];
+    word assign_data_length = 1;
+
+    features[0] = 0;
+    pC->xbuffer[0] = 0;
+    preq = (IDI_SYNC_REQ*)&buffer[0];
+    preq->xdi_extended_features.Req = 0;
+    preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
+    preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
+    preq->xdi_extended_features.info.features = &features[0];
+
+    (*(pC->request))((ENTITY*)preq);
+
+    if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) &&
+        (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) {
+      dword rx_dma_magic;
+      if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) {
+        pC->xbuffer[0] = LLI;
+        pC->xbuffer[1] = 8;
+        pC->xbuffer[2] = 0x40;
+        pC->xbuffer[3] = (byte)pC->dma_handle;
+        pC->xbuffer[4] = (byte)rx_dma_magic;
+        pC->xbuffer[5] = (byte)(rx_dma_magic >>  8);
+        pC->xbuffer[6] = (byte)(rx_dma_magic >> 16);
+        pC->xbuffer[7] = (byte)(rx_dma_magic >> 24);
+        pC->xbuffer[8] = (byte)DIVA_MAX_MANAGEMENT_TRANSFER_SIZE;
+        pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8);
+        pC->xbuffer[10] = 0;
+
+        assign_data_length = 11;
+      }
+    } else {
+      pC->dma_handle = -1;
+    }
 
     e->Id          = MAN_ID;
     e->callback    = diva_maint_xdi_cb;
@@ -1149,9 +1216,8 @@
     e->X           = &pC->XData;
     e->Req         = ASSIGN;
     e->ReqCh       = 0;
-    e->X->PLength  = 1;
+    e->X->PLength  = assign_data_length;
     e->X->P        = (byte*)&pC->xbuffer[0];
-    pC->xbuffer[0] = 0;
 
     pC->request_pending = 1;
 
@@ -1300,16 +1366,25 @@
   diva_os_spin_lock_magic_t old_irql, old_irql1;
 
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "xdi_cb");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "xdi_cb");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
 
   pC = (diva_maint_client_t*)pLib->hAdapter;
 
-	if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
-    diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error");
+  if ((e->complete == 255) || (pC->dma_handle < 0)) {
+    if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
+      diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error");
+    }
+  } else {
+    /*
+      Process combined management interface indication
+      */
+    if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
+      diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error (DMA mode)");
+    }
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "xdi_cb");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
 
 
 	if (pC->request_pending) {
@@ -1317,7 +1392,7 @@
     (*(pC->request))(e);
 	}
 
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "xdi_cb");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
 }
 
 
@@ -1365,8 +1440,42 @@
   }
 
   switch (notify_subject) {
-    case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE:
-      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS) {
+    case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: {
+      int view = (TraceFilter[0] == 0);
+      /*
+        Process selective Trace
+        */
+      if (channel->Line[0] == 'I' && channel->Line[1] == 'd' &&
+          channel->Line[2] == 'l' && channel->Line[3] == 'e') {
+        if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) {
+          (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0);
+          (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0);
+          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d",
+                                     (int)channel->ChannelNumber);
+          TraceFilterIdent   = -1;
+          TraceFilterChannel = -1;
+          view = 1;
+        }
+      } else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr (&channel->RemoteAddress[0]) &&
+                                                               diva_mnt_cmp_nmbr (&channel->LocalAddress[0]))) {
+
+        if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */
+          (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1);
+        }
+        if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */
+          (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1);
+        }
+
+        TraceFilterIdent   = pC->hDbg->id;
+        TraceFilterChannel = (int)channel->ChannelNumber;
+
+        if (TraceFilterIdent >= 0) {
+          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d",
+                                     (int)channel->ChannelNumber);
+          view = 1;
+        }
+      }
+      if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) {
         diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Ch     = %d",
                                                                      (int)channel->ChannelNumber);
         diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]);
@@ -1392,10 +1501,26 @@
                                                                     channel->LastDisconnecCause);
         diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Owner  = <%s>", &channel->UserID[0]);
       }
-      break;
+
+		} break;
 
     case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE:
       if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) {
+				{
+					int ch = TraceFilterChannel;
+					int id = TraceFilterIdent;
+
+					if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
+						if (ch != (int)modem->ChannelNumber) {
+							break;
+						}
+					} else if (TraceFilter[0] != 0) {
+						break;
+					}
+				}
+
+
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch    = %lu",
                                                                      (int)modem->ChannelNumber);
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu",     modem->Event);
@@ -1428,6 +1553,20 @@
 
     case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE:
       if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) {
+				{
+					int ch = TraceFilterChannel;
+					int id = TraceFilterIdent;
+
+					if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
+						if (ch != (int)fax->ChannelNumber) {
+							break;
+						}
+					} else if (TraceFilter[0] != 0) {
+						break;
+					}
+				}
+
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch    = %lu",(int)fax->ChannelNumber);
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu",     fax->Event);
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu",     fax->Page_Counter);
@@ -1660,6 +1799,52 @@
   diva_dbg_entry_head_t* pmsg;
   word size;
   dword sec, usec;
+  int ch = TraceFilterChannel;
+  int id = TraceFilterIdent;
+
+  /*
+    Selective trace
+    */
+  if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+      (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
+    const char* p = 0;
+    int ch_value = -1;
+    MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer;
+
+    if (Adapter != clients[id].logical) {
+      return; /* Ignore all trace messages from other adapters */
+    }
+
+    if (TrcData->code == 24) {
+      p = (char*)&TrcData->code;
+      p += 2;
+    }
+
+    /*
+      All L1 messages start as [dsp,ch], so we can filter this information
+      and filter out all messages that use different channel
+      */
+    if (p && p[0] == '[') {
+      if (p[2] == ',') {
+        p += 3;
+        ch_value = *p - '0';
+      } else if (p[3] == ',') {
+        p += 4;
+        ch_value = *p - '0';
+      }
+      if (ch_value >= 0) {
+        if (p[2] == ']') {
+          ch_value = ch_value * 10 + p[1] - '0';
+        }
+        if (ch_value != ch) {
+          return; /* Ignore other channels */
+        }
+      }
+    }
+
+	} else if (TraceFilter[0] != 0) {
+    return; /* Ignore trace if trace filter is activated, but idle */
+  }
 
   diva_os_get_time (&sec, &usec);
 
@@ -1705,18 +1890,20 @@
       (*(pC->pIdiLib->DivaSTraceSetDChannel))(pC->pIdiLib,
                                               (pC->hDbg->dbgMask & DIVA_MGT_DBG_DCHAN) != 0);
     }
-    if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) {
-      int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
+    if (!TraceFilter[0]) {
+      if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) {
+        int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
 
-      for (i = 0; i < pC->channels; i++) {
-        (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state);
+        for (i = 0; i < pC->channels; i++) {
+          (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state);
+        }
       }
-    }
-    if (changed & DIVA_MGT_DBG_IFC_AUDIO) {
-      int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
+      if (changed & DIVA_MGT_DBG_IFC_AUDIO) {
+        int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
 
-      for (i = 0; i < pC->channels; i++) {
-        (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state);
+        for (i = 0; i < pC->channels; i++) {
+          (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state);
+        }
       }
     }
   }
@@ -1743,8 +1930,8 @@
   for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
     pmem = NULL;
 
-    diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "unload");
-    diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "unload");
+    diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
+    diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "unload");
 
     if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
       if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) {
@@ -1759,19 +1946,31 @@
           clients[i].pmem = NULL;
         }
         clients[i].hDbg    = NULL;
-        clients[i].request = NULL;
         clients[i].request_pending = 0;
+
+        if (clients[i].dma_handle >= 0) {
+          /*
+            Free DMA handle
+            */
+          diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
+          clients[i].dma_handle = -1;
+				}
+        clients[i].request = NULL;
       } else {
         fret = -1;
       }
     }
 
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "unload");
+    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "unload");
     if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
       clients[i].request_pending = 0;
       (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
+      if (clients[i].dma_handle >= 0) {
+        diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
+        clients[i].dma_handle = -1;
+      }
     }
-    diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "unload");
+    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
 
     if (pmem) {
       diva_os_free (0, pmem);
@@ -1779,5 +1978,158 @@
   }
 
   return (fret);
+}
+
+/*
+  Set/Read the trace filter used for selective tracing.
+  Affects B- and Audio Tap trace mask at run time
+  */
+int diva_set_trace_filter (int filter_length, const char* filter) {
+  diva_os_spin_lock_magic_t old_irql, old_irql1;
+  int i, ch, on, client_b_on, client_atap_on;
+
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+
+  if (filter_length <= DIVA_MAX_SELECTIVE_FILTER_LENGTH) {
+    memcpy (&TraceFilter[0], filter, filter_length);
+    if (TraceFilter[filter_length]) {
+      TraceFilter[filter_length] = 0;
+    }
+    if (TraceFilter[0] == '*') {
+      TraceFilter[0] = 0;
+    }
+  } else {
+    filter_length = -1;
+  }
+
+  TraceFilterIdent   = -1;
+  TraceFilterChannel = -1;
+
+  on = (TraceFilter[0] == 0);
+
+  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
+      client_b_on    = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
+      client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO)    != 0);
+      for (ch = 0; ch < clients[i].channels; ch++) {
+        (*(clients[i].pIdiLib->DivaSTraceSetBChannel))(clients[i].pIdiLib->hLib, ch+1, client_b_on);
+        (*(clients[i].pIdiLib->DivaSTraceSetAudioTap))(clients[i].pIdiLib->hLib, ch+1, client_atap_on);
+      }
+    }
+  }
+
+  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
+      diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+      clients[i].request_pending = 0;
+      (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
+      diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+    }
+  }
+
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
+
+  return (filter_length);
+}
+
+int diva_get_trace_filter (int max_length, char* filter) {
+  diva_os_spin_lock_magic_t old_irql;
+  int len;
+
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
+  len = strlen (&TraceFilter[0]) + 1;
+  if (max_length >= len) {
+    memcpy (filter, &TraceFilter[0], len);
+  }
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
+
+  return (len);
+}
+
+static int diva_dbg_cmp_key (const char* ref, const char* key) {
+	while (*key && (*ref++ == *key++));
+  return (!*key && !*ref);
+}
+
+/*
+  In case trace filter starts with "C" character then
+  all following characters are interpreted as command.
+  Followings commands are available:
+  - single, trace single call at time, independent from CPN/CiPN
+  */
+static int diva_mnt_cmp_nmbr (const char* nmbr) {
+  const char* ref = &TraceFilter[0];
+  int ref_len = strlen(&TraceFilter[0]), nmbr_len = strlen(nmbr);
+
+  if (ref[0] == 'C') {
+    if (diva_dbg_cmp_key (&ref[1], "single")) {
+      return (0);
+    }
+    return (-1);
+  }
+
+  if (!ref_len || (ref_len > nmbr_len)) {
+    return (-1);
+  }
+
+  nmbr = nmbr + nmbr_len - 1;
+  ref  = ref  + ref_len  - 1;
+
+  while (ref_len--) {
+    if (*nmbr-- != *ref--) {
+      return (-1);
+    }
+  }
+
+  return (0);
+}
+
+static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic) {
+  ENTITY e;
+  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
+
+  if (!request) {
+    return (-1);
+  }
+
+  pReq->xdi_dma_descriptor_operation.Req = 0;
+  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
+
+  pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_address = 0;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
+
+  (*request)((ENTITY*)pReq);
+
+  if (!pReq->xdi_dma_descriptor_operation.info.operation &&
+      (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
+      pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
+    *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
+    return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
+  } else {
+    return (-1);
+  }
+}
+
+static void diva_free_dma_descriptor (IDI_CALL request, int nr) {
+  ENTITY e;
+  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
+
+  if (!request || (nr < 0)) {
+    return;
+  }
+
+  pReq->xdi_dma_descriptor_operation.Req = 0;
+  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
+
+  pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_address = 0;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
+
+  (*request)((ENTITY*)pReq);
 }
 
diff -Nru a/drivers/isdn/hardware/eicon/debug_if.h b/drivers/isdn/hardware/eicon/debug_if.h
--- a/drivers/isdn/hardware/eicon/debug_if.h	2002-10-10 20:08:55 -07:00
+++ b/drivers/isdn/hardware/eicon/debug_if.h	2004-08-28 13:14:29 -07:00
@@ -57,12 +57,18 @@
 void diva_mnt_add_xdi_adapter    (const DESCRIPTOR* d);
 int diva_mnt_shutdown_xdi_adapters (void);
 
+#define DIVA_MAX_SELECTIVE_FILTER_LENGTH 127
+int diva_set_trace_filter (int filter_length, const char* filter);
+int diva_get_trace_filter (int max_length,    char*       filter);
+
 
 #define DITRACE_CMD_GET_DRIVER_INFO   1
 #define DITRACE_READ_DRIVER_DBG_MASK  2
 #define DITRACE_WRITE_DRIVER_DBG_MASK 3
 #define DITRACE_READ_TRACE_ENTRY      4
 #define DITRACE_READ_TRACE_ENTRYS     5
+#define DITRACE_WRITE_SELECTIVE_TRACE_FILTER 6
+#define DITRACE_READ_SELECTIVE_TRACE_FILTER  7
 
 /*
   Trace lavels for debug via management interface
diff -Nru a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h
--- a/drivers/isdn/hardware/eicon/debuglib.h	2003-09-17 03:42:12 -07:00
+++ b/drivers/isdn/hardware/eicon/debuglib.h	2004-08-28 13:14:29 -07:00
@@ -232,7 +232,7 @@
 typedef void ( * DbgEnd) (pDbgHandle) ;
 typedef void ( * DbgLog) (unsigned short, int, char *, va_list) ;
 typedef void ( * DbgOld) (unsigned short, char *, va_list) ;
-typedef void ( * DbgEv)  (unsigned short, unsigned int, va_list) ;
+typedef void ( * DbgEv)  (unsigned short, unsigned long, va_list) ;
 typedef void ( * DbgIrq) (unsigned short, int, char *, va_list) ;
 typedef struct _DbgHandle_
 { char    Registered ; /* driver successfull registered */
@@ -259,7 +259,7 @@
  void      *pReserved3 ;
 } _DbgHandle_ ;
 extern _DbgHandle_ myDriverDebugHandle ;
-typedef struct
+typedef struct _OldDbgHandle_
 { struct _OldDbgHandle_ *next ;
  void                *pIrp ;
  long    regTime[2] ;
@@ -310,7 +310,7 @@
             unsigned long   B_ChannelMask;
             unsigned long   LogBufferSize;
         } CardTrace;
-    } u1;     
+    }Data;     
 } _DbgExtendedInfo_;
 #ifndef DIVA_NO_DEBUGLIB
 /* -------------------------------------------------------------
diff -Nru a/drivers/isdn/hardware/eicon/diddfunc.c b/drivers/isdn/hardware/eicon/diddfunc.c
--- a/drivers/isdn/hardware/eicon/diddfunc.c	2004-07-12 01:01:03 -07:00
+++ b/drivers/isdn/hardware/eicon/diddfunc.c	2004-08-28 13:14:29 -07:00
@@ -1,4 +1,4 @@
-/* $Id: diddfunc.c,v 1.14 2003/08/25 10:06:37 schindler Exp $
+/* $Id: diddfunc.c,v 1.14.6.2 2004/08/28 20:03:53 armin Exp $
  *
  * DIDD Interface module for Eicon active cards.
  * 
@@ -15,8 +15,6 @@
 #include "di_defs.h"
 #include "dadapter.h"
 #include "divasync.h"
-
-#define MAX_DESCRIPTORS  32
 
 #define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
diff -Nru a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
--- a/drivers/isdn/hardware/eicon/diva_didd.c	2003-09-09 03:02:58 -07:00
+++ b/drivers/isdn/hardware/eicon/diva_didd.c	2004-08-28 13:14:29 -07:00
@@ -1,4 +1,4 @@
-/* $Id: diva_didd.c,v 1.13 2003/08/27 10:11:21 schindler Exp $
+/* $Id: diva_didd.c,v 1.13.6.1 2004/08/28 20:03:53 armin Exp $
  *
  * DIDD Interface module for Eicon active cards.
  * 
@@ -23,7 +23,7 @@
 #include "divasync.h"
 #include "did_vers.h"
 
-static char *main_revision = "$Revision: 1.13 $";
+static char *main_revision = "$Revision: 1.13.6.1 $";
 
 static char *DRIVERNAME =
     "Eicon DIVA - DIDD table (http://www.melware.net)";
@@ -36,8 +36,6 @@
 MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
 MODULE_SUPPORTED_DEVICE("Eicon diva drivers");
 MODULE_LICENSE("GPL");
-
-#define MAX_DESCRIPTORS  32
 
 #define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
diff -Nru a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
--- a/drivers/isdn/hardware/eicon/divamnt.c	2004-08-08 14:07:47 -07:00
+++ b/drivers/isdn/hardware/eicon/divamnt.c	2004-08-28 13:14:29 -07:00
@@ -1,4 +1,4 @@
-/* $Id: divamnt.c,v 1.32 2004/01/15 09:48:13 armin Exp $
+/* $Id: divamnt.c,v 1.32.6.5 2004/08/28 20:03:53 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * Maint module
@@ -17,8 +17,6 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
 #include <linux/devfs_fs_kernel.h>
 
 #include "platform.h"
@@ -26,7 +24,7 @@
 #include "divasync.h"
 #include "debug_if.h"
 
-static char *main_revision = "$Revision: 1.32 $";
+static char *main_revision = "$Revision: 1.32.6.5 $";
 
 static int major;
 
@@ -47,8 +45,7 @@
 char *DRIVERRELEASE_MNT = "2.0";
 
 static wait_queue_head_t msgwaitq;
-static DECLARE_MUTEX(opened_sem);
-static int opened;
+static unsigned long opened;
 static struct timeval start_time;
 
 extern int mntfunc_init(int *, void **, unsigned long);
@@ -74,20 +71,6 @@
 }
 
 /*
- * buffer alloc
- */
-void *diva_os_malloc_tbuffer(unsigned long flags, unsigned long size)
-{
-	return (kmalloc(size, GFP_KERNEL));
-}
-void diva_os_free_tbuffer(unsigned long flags, void *ptr)
-{
-	if (ptr) {
-		kfree(ptr);
-	}
-}
-
-/*
  * kernel/user space copy functions
  */
 int diva_os_copy_to_user(void *os_handle, void __user *dst, const void *src,
@@ -131,154 +114,8 @@
 }
 
 /*
- * /proc entries
+ * device node operations
  */
-
-extern struct proc_dir_entry *proc_net_eicon;
-static struct proc_dir_entry *maint_proc_entry = NULL;
-
-/*
-	Read function is provided for compatibility reason - this allows
-  to read unstructured traces, formated as ascii string only
-  */
-static ssize_t
-maint_read(struct file *file, char __user *buf, size_t count, loff_t * off)
-{
-	diva_dbg_entry_head_t *pmsg = NULL;
-	diva_os_spin_lock_magic_t old_irql;
-	word size;
-	char *pstr, *dli_label = "UNK";
-	int str_length;
-	int *str_msg;
-
-	if (!file->private_data) {
-		for (;;) {
-			while (
-			       (pmsg =
-				diva_maint_get_message(&size,
-						       &old_irql))) {
-				if (!(pmsg->facility == MSG_TYPE_STRING)) {
-					diva_maint_ack_message(1,
-							       &old_irql);
-				} else {
-					break;
-				}
-			}
-
-			if (!pmsg) {
-				if (file->f_flags & O_NONBLOCK) {
-					return (-EAGAIN);
-				}
-				interruptible_sleep_on(&msgwaitq);
-				if (signal_pending(current)) {
-					return (-ERESTARTSYS);
-				}
-			} else {
-				break;
-			}
-		}
-		/*
-		   The length of message that shoule be read is:
-		   pmsg->data_length + label(25) + DrvID(2) + byte CR + trailing zero
-		 */
-		if (!
-		    (str_msg =
-		     (int *) diva_os_malloc_tbuffer(0,
-						    pmsg->data_length +
-						    29 + 2 * sizeof(int)))) {
-			diva_maint_ack_message(0, &old_irql);
-			return (-ENOMEM);
-		}
-		pstr = (char *) &str_msg[2];
-
-		switch (pmsg->dli) {
-		case DLI_LOG:
-			dli_label = "LOG";
-			break;
-		case DLI_FTL:
-			dli_label = "FTL";
-			break;
-		case DLI_ERR:
-			dli_label = "ERR";
-			break;
-		case DLI_TRC:
-			dli_label = "TRC";
-			break;
-		case DLI_REG:
-			dli_label = "REG";
-			break;
-		case DLI_MEM:
-			dli_label = "MEM";
-			break;
-		case DLI_SPL:
-			dli_label = "SPL";
-			break;
-		case DLI_IRP:
-			dli_label = "IRP";
-			break;
-		case DLI_TIM:
-			dli_label = "TIM";
-			break;
-		case DLI_TAPI:
-			dli_label = "TAPI";
-			break;
-		case DLI_NDIS:
-			dli_label = "NDIS";
-			break;
-		case DLI_CONN:
-			dli_label = "CONN";
-			break;
-		case DLI_STAT:
-			dli_label = "STAT";
-			break;
-		case DLI_PRV0:
-			dli_label = "PRV0";
-			break;
-		case DLI_PRV1:
-			dli_label = "PRV1";
-			break;
-		case DLI_PRV2:
-			dli_label = "PRV2";
-			break;
-		case DLI_PRV3:
-			dli_label = "PRV3";
-			break;
-		}
-		str_length = sprintf(pstr, "%s %02x %s\n",
-				     dli_label, (byte) pmsg->drv_id,
-				     (char *) &pmsg[1]);
-		str_msg[0] = str_length;
-		str_msg[1] = 0;
-		file->private_data = str_msg;
-		diva_maint_ack_message(1, &old_irql);
-	} else {
-		str_msg = (int *) file->private_data;
-		pstr = (char *) &str_msg[2];
-		pstr += str_msg[1];	/* head + offset */
-		str_length = str_msg[0] - str_msg[1];	/* length - offset */
-	}
-	str_length = MIN(str_length, count);
-
-	if (diva_os_copy_to_user(NULL, buf, pstr, str_length)) {
-		diva_os_free_tbuffer(0, str_msg);
-		file->private_data = NULL;
-		return (-EFAULT);
-	}
-	str_msg[1] += str_length;
-	if ((str_msg[0] - str_msg[1]) <= 0) {
-		diva_os_free_tbuffer(0, str_msg);
-		file->private_data = NULL;
-	}
-
-	return (str_length);
-}
-
-static ssize_t
-maint_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
-{
-	return (-ENODEV);
-}
-
 static unsigned int maint_poll(struct file *file, poll_table * wait)
 {
 	unsigned int mask = 0;
@@ -293,13 +130,10 @@
 
 static int maint_open(struct inode *ino, struct file *filep)
 {
-	down(&opened_sem);
-	if (opened) {
-		up(&opened_sem);
+	/* only one open is allowed, so we test
+	   it atomically */
+	if (test_and_set_bit(0, &opened))
 		return (-EBUSY);
-	}
-	opened++;
-	up(&opened_sem);
 
 	filep->private_data = NULL;
 
@@ -309,54 +143,16 @@
 static int maint_close(struct inode *ino, struct file *filep)
 {
 	if (filep->private_data) {
-		diva_os_free_tbuffer(0, filep->private_data);
-		filep->private_data = NULL;
+		diva_os_free(0, filep->private_data);
+		filep->private_data = 0;
 	}
 
-	down(&opened_sem);
-	opened--;
-	up(&opened_sem);
+	/* clear 'used' flag */
+	clear_bit(0, &opened);
+	
 	return (0);
 }
 
-/*
- * fops
- */
-static struct file_operations maint_fops = {
-	.owner   = THIS_MODULE,
-	.llseek  = no_llseek,
-	.read    = maint_read,
-	.write   = maint_write,
-	.poll    = maint_poll,
-	.open    = maint_open,
-	.release = maint_close
-};
-
-static int DIVA_INIT_FUNCTION create_maint_proc(void)
-{
-	maint_proc_entry =
-	    create_proc_entry("maint", S_IFREG | S_IRUGO | S_IWUSR,
-			      proc_net_eicon);
-	if (!maint_proc_entry)
-		return (0);
-
-	maint_proc_entry->proc_fops = &maint_fops;
-	maint_proc_entry->owner = THIS_MODULE;
-
-	return (1);
-}
-
-static void remove_maint_proc(void)
-{
-	if (maint_proc_entry) {
-		remove_proc_entry("maint", proc_net_eicon);
-		maint_proc_entry = NULL;
-	}
-}
-
-/*
- * device node operations
- */
 static ssize_t divas_maint_write(struct file *file, const char __user *buf,
 				 size_t count, loff_t * ppos)
 {
@@ -427,18 +223,10 @@
 		ret = -EIO;
 		goto out;
 	}
-	if (!create_maint_proc()) {
-		printk(KERN_ERR "%s: failed to create proc entry.\n",
-		       DRIVERLNAME);
-		divas_maint_unregister_chrdev();
-		ret = -EIO;
-		goto out;
-	}
 
 	if (!(mntfunc_init(&buffer_length, &buffer, diva_dbg_mem))) {
 		printk(KERN_ERR "%s: failed to connect to DIDD.\n",
 		       DRIVERLNAME);
-		remove_maint_proc();
 		divas_maint_unregister_chrdev();
 		ret = -EIO;
 		goto out;
@@ -457,7 +245,6 @@
 */
 static void DIVA_EXIT_FUNCTION maint_exit(void)
 {
-	remove_maint_proc();
 	divas_maint_unregister_chrdev();
 	mntfunc_finit();
 
@@ -466,3 +253,4 @@
 
 module_init(maint_init);
 module_exit(maint_exit);
+
diff -Nru a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
--- a/drivers/isdn/hardware/eicon/divasfunc.c	2004-07-12 01:01:03 -07:00
+++ b/drivers/isdn/hardware/eicon/divasfunc.c	2004-08-28 13:14:29 -07:00
@@ -1,4 +1,4 @@
-/* $Id: divasfunc.c,v 1.23 2004/04/08 01:17:57 armin Exp $
+/* $Id: divasfunc.c,v 1.23.4.2 2004/08/28 20:03:53 armin Exp $
  *
  * Low level driver for Eicon DIVA Server ISDN cards.
  *
@@ -27,8 +27,6 @@
 
 extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
 
-#define MAX_DESCRIPTORS  32
-
 extern char *DRIVERRELEASE_DIVAS;
 
 static dword notify_handle;
@@ -76,10 +74,10 @@
 		d.features = IoAdapters[card - 1]->Properties.Features;
 		DBG_TRC(("DIDD register A(%d) channels=%d", card,
 			 d.channels))
-		/* workaround for different Name in structure */
-		strlcpy(IoAdapters[card - 1]->Name,
-			IoAdapters[card - 1]->Properties.Name,
-			sizeof(IoAdapters[card - 1]->Name));
+		    /* workaround for different Name in structure */
+		    strlcpy(IoAdapters[card - 1]->Name,
+			    IoAdapters[card - 1]->Properties.Name,
+			    sizeof(IoAdapters[card - 1]->Name));
 		req.didd_remove_adapter.e.Req = 0;
 		req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
 		req.didd_add_adapter.info.descriptor = (void *) &d;
diff -Nru a/drivers/isdn/hardware/eicon/divasync.h b/drivers/isdn/hardware/eicon/divasync.h
--- a/drivers/isdn/hardware/eicon/divasync.h	2002-10-10 20:08:59 -07:00
+++ b/drivers/isdn/hardware/eicon/divasync.h	2004-08-28 13:14:29 -07:00
@@ -31,33 +31,31 @@
 #define IDI_SYNC_REQ_SET_POSTCALL       0x03
 #define IDI_SYNC_REQ_GET_XLOG           0x04
 #define IDI_SYNC_REQ_GET_FEATURES       0x05
-/* Added for DIVA USB support */
 #define IDI_SYNC_REQ_USB_REGISTER       0x06
 #define IDI_SYNC_REQ_USB_RELEASE        0x07
 #define IDI_SYNC_REQ_USB_ADD_DEVICE     0x08
 #define IDI_SYNC_REQ_USB_START_DEVICE   0x09
 #define IDI_SYNC_REQ_USB_STOP_DEVICE    0x0A
 #define IDI_SYNC_REQ_USB_REMOVE_DEVICE  0x0B
-/* Added for Diva Server Monitor */
 #define IDI_SYNC_REQ_GET_CARDTYPE       0x0C
 #define IDI_SYNC_REQ_GET_DBG_XLOG       0x0D
-#define IDI_SYNC_REQ_GET_LINE_IDX   0x0E
 #define DIVA_USB
 #define DIVA_USB_REQ                    0xAC
 #define DIVA_USB_TEST                   0xAB
 #define DIVA_USB_ADD_ADAPTER            0xAC
 #define DIVA_USB_REMOVE_ADAPTER         0xAD
-/******************************************************************************/
 #define IDI_SYNC_REQ_SERIAL_HOOK        0x80
 #define IDI_SYNC_REQ_XCHANGE_STATUS     0x81
 #define IDI_SYNC_REQ_USB_HOOK           0x82
 #define IDI_SYNC_REQ_PORTDRV_HOOK       0x83
-#define IDI_SYNC_REQ_SLI           (0x84)   /*  SLI request from 3signal modem drivers */
+#define IDI_SYNC_REQ_SLI                0x84   /*  SLI request from 3signal modem drivers */
 #define IDI_SYNC_REQ_RECONFIGURE        0x85
 #define IDI_SYNC_REQ_RESET              0x86
+#define IDI_SYNC_REQ_GET_85X_DEVICE_DATA     0x87
 #define IDI_SYNC_REQ_LOCK_85X                   0x88
+#define IDI_SYNC_REQ_DIVA_85X_USB_DATA_EXCHANGE 0x99
+#define IDI_SYNC_REQ_DIPORT_EXCHANGE_REQ   0x98
 #define IDI_SYNC_REQ_GET_85X_EXT_PORT_TYPE      0xA0
-#define IDI_SYNC_REQ_DIPORT_GET_85X_TX_CTRL_FN  0x98
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES  0x92
 /*
@@ -87,6 +85,8 @@
 #define DIVA_XDI_EXTENDED_FEATURE_CAPI_PRMS       0x08
 #define DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC    0x10
 #define DIVA_XDI_EXTENDED_FEATURE_RX_DMA          0x20
+#define DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA  0x40
+#define DIVA_XDI_EXTENDED_FEATURE_WIDE_ID         0x80
 #define DIVA_XDI_EXTENDED_FEATURES_MAX_SZ    1
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR   0x93
@@ -115,6 +115,7 @@
 typedef struct _diva_xdi_get_logical_adapter_number {
   dword logical_adapter_number;
   dword controller;
+  dword total_controllers;
 } diva_xdi_get_logical_adapter_number_s_t;
 /******************************************************************************/
 #define IDI_SYNC_REQ_UP1DM_OPERATION   0x96
@@ -134,6 +135,7 @@
 #define IDI_SYNC_REQ_DIDD_ADD_ADAPTER               0x03
 #define IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER            0x04
 #define IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY        0x05
+#define IDI_SYNC_REQ_DIDD_GET_CFG_LIB_IFC           0x10
 typedef struct _diva_didd_adapter_notify {
  dword handle; /* Notification handle */
  void   * callback;
@@ -149,6 +151,9 @@
  void   * buffer;
  dword length;
 } diva_didd_read_adapter_array_t;
+typedef struct _diva_didd_get_cfg_lib_ifc {
+ void* ifc;
+} diva_didd_get_cfg_lib_ifc_t;
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_STREAM    0x91
 #define DIVA_XDI_SYNCHRONOUS_SERVICE   0x01
@@ -466,6 +471,10 @@
   ENTITY             e;
   diva_didd_read_adapter_array_t info;
  } didd_read_adapter_array;
+ struct {
+  ENTITY             e;
+  diva_didd_get_cfg_lib_ifc_t     info;
+ } didd_get_cfg_lib_ifc;
   struct {
     unsigned char Req;
     unsigned char Rc;
diff -Nru a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
--- a/drivers/isdn/hardware/eicon/idifunc.c	2004-07-12 01:01:03 -07:00
+++ b/drivers/isdn/hardware/eicon/idifunc.c	2004-08-28 13:14:29 -07:00
@@ -1,4 +1,4 @@
-/* $Id: idifunc.c,v 1.14.4.2 2004/05/09 16:42:20 armin Exp $
+/* $Id: idifunc.c,v 1.14.4.4 2004/08/28 20:03:53 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * User Mode IDI Interface 
@@ -24,8 +24,6 @@
 extern void DIVA_DIDD_Read(void *, int);
 extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int);
 extern void diva_user_mode_idi_remove_adapter(int);
-
-#define MAX_DESCRIPTORS  32
 
 static dword notify_handle;
 static DESCRIPTOR DAdapter;
diff -Nru a/drivers/isdn/hardware/eicon/io.c b/drivers/isdn/hardware/eicon/io.c
--- a/drivers/isdn/hardware/eicon/io.c	2003-09-09 03:02:58 -07:00
+++ b/drivers/isdn/hardware/eicon/io.c	2004-08-28 13:14:29 -07:00
@@ -77,6 +77,7 @@
 #if defined(DIVA_IDI_RX_DMA)
   DIVA_XDI_EXTENDED_FEATURE_CMA          |
   DIVA_XDI_EXTENDED_FEATURE_RX_DMA       |
+  DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA |
 #endif
   DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC),
  0
@@ -226,8 +227,10 @@
         if (pI->descriptor_number >= 0) {
           dword dma_magic;
           void* local_addr;
+#if 0
           DBG_TRC(("A(%d) dma_alloc(%d)",
                    IoAdapter->ANum, pI->descriptor_number))
+#endif
           diva_get_dma_map_entry (\
                                (struct _diva_dma_map_entry*)IoAdapter->dma_map,
                                pI->descriptor_number,
@@ -240,7 +243,9 @@
         }
       } else if ((pI->operation == IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE) &&
                  (pI->descriptor_number >= 0)) {
+#if 0
         DBG_TRC(("A(%d) dma_free(%d)", IoAdapter->ANum, pI->descriptor_number))
+#endif
         diva_free_dma_map_entry((struct _diva_dma_map_entry*)IoAdapter->dma_map,
                                 pI->descriptor_number);
         pI->descriptor_number = -1;
@@ -257,6 +262,7 @@
                                      &syncReq->xdi_logical_adapter_number.info;
       pI->logical_adapter_number = IoAdapter->ANum;
       pI->controller = IoAdapter->ControllerNumber;
+      pI->total_controllers = IoAdapter->Properties.Adapters;
     } return;
     case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: {
        diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info;
@@ -318,6 +324,16 @@
    }
    syncReq->GetSerial.serial = 0 ;
    break ;
+  case IDI_SYNC_REQ_GET_CARDTYPE:
+   if ( IoAdapter )
+   {
+    syncReq->GetCardType.cardtype = IoAdapter->cardType ;
+    DBG_TRC(("xdi: Adapter %d / CardType %ld",
+             IoAdapter->ANum, IoAdapter->cardType))
+    return ;
+   }
+   syncReq->GetCardType.cardtype = 0 ;
+   break ;
   case IDI_SYNC_REQ_GET_XLOG:
    if ( IoAdapter )
    {
@@ -326,6 +342,14 @@
    }
    e->Ind = 0 ;
    break ;
+  case IDI_SYNC_REQ_GET_DBG_XLOG:
+   if ( IoAdapter )
+   {
+    pcm_req (IoAdapter, e) ;
+    return ;
+   }
+   e->Ind = 0 ;
+   break ;
   case IDI_SYNC_REQ_GET_FEATURES:
    if ( IoAdapter )
    {
@@ -345,7 +369,9 @@
   }
   if ( IoAdapter )
   {
+#if 0
    DBG_FTL(("xdi: unknown Req 0 / Rc %d !", e->Rc))
+#endif
    return ;
   }
  }
@@ -496,7 +522,7 @@
   diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
                &OldIrql,
                "data_pcm_1");
-  IoAdapter->pcm_data = (unsigned long)pcm;
+  IoAdapter->pcm_data = (void *)pcm;
   IoAdapter->pcm_pending = 1;
   diva_os_schedule_soft_isr (&IoAdapter->req_soft_isr);
   diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
@@ -510,7 +536,7 @@
                  &OldIrql,
                  "data_pcm_3");
     IoAdapter->pcm_pending = 0;
-    IoAdapter->pcm_data   = 0;
+    IoAdapter->pcm_data    = NULL ;
     diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
                  &OldIrql,
                  "data_pcm_3");
@@ -528,7 +554,7 @@
                &OldIrql,
                "data_pcm_4");
   IoAdapter->pcm_pending = 0;
-  IoAdapter->pcm_data   = 0;
+  IoAdapter->pcm_data    = NULL ;
   diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
                &OldIrql,
                "data_pcm_4");
@@ -668,7 +694,7 @@
 void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len)
 {
   byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
- byte* P = (byte*)buffer;
+  byte* P = (byte*)buffer;
   if ((long)adr & 1) {
     outppw(Port+4, (word)(unsigned long)adr);
     *P = inpp(Port);
@@ -678,7 +704,7 @@
     if (!len) {
 	DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 	return;
-  }
+    }
   }
   outppw(Port+4, (word)(unsigned long)adr);
   inppw_buffer (Port, P, len+1);
@@ -710,7 +736,7 @@
 void io_out_buffer(ADAPTER * a, void * adr, void * buffer, word len)
 {
   byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
- byte* P = (byte*)buffer;
+  byte* P = (byte*)buffer;
   if ((long)adr & 1) {
     outppw(Port+4, (word)(unsigned long)adr);
     outpp(Port, *P);
@@ -839,21 +865,21 @@
 /* --------------------------------------------------------------------------
   routines for aligned reading and writing on RISC
   -------------------------------------------------------------------------- */
-void outp_words_from_buffer (word* adr, byte* P, word len)
+void outp_words_from_buffer (word* adr, byte* P, dword len)
 {
-  word i = 0;
+  dword i = 0;
   word w;
-  while (i < (len & 0xfffe)) {
+  while (i < (len & 0xfffffffe)) {
     w = P[i++];
     w += (P[i++])<<8;
     outppw (adr, w);
   }
 }
-void inp_words_to_buffer (word* adr, byte* P, word len)
+void inp_words_to_buffer (word* adr, byte* P, dword len)
 {
-  word i = 0;
+  dword i = 0;
   word w;
-  while (i < (len & 0xfffe)) {
+  while (i < (len & 0xfffffffe)) {
     w = inppw (adr);
     P[i++] = (byte)(w);
     P[i++] = (byte)(w>>8);
diff -Nru a/drivers/isdn/hardware/eicon/io.h b/drivers/isdn/hardware/eicon/io.h
--- a/drivers/isdn/hardware/eicon/io.h	2003-09-09 03:02:58 -07:00
+++ b/drivers/isdn/hardware/eicon/io.h	2004-08-28 13:14:29 -07:00
@@ -40,6 +40,14 @@
  PISDN_ADAPTER QuadroAdapter[4] ;
 } ADAPTER_LIST_ENTRY, *PADAPTER_LIST_ENTRY ;
 /* --------------------------------------------------------------------------
+  Special OS memory support structures
+  -------------------------------------------------------------------------- */
+#define MAX_MAPPED_ENTRIES 8
+typedef struct {
+ void  * Address;
+ dword    Length;
+} ADAPTER_MEMORY ;
+/* --------------------------------------------------------------------------
   Configuration of XDI clients carried by XDI
   -------------------------------------------------------------------------- */
 #define DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON      0x01
@@ -52,6 +60,7 @@
   -------------------------------------------------------------------------- */
 struct _ISDN_ADAPTER {
  void             (* DIRequest)(PISDN_ADAPTER, ENTITY *) ;
+ int                 State ; /* from NT4 1.srv, a good idea, but  a poor achievment */
  int                 Initialized ;
  int         RegisteredWithDidd ;
  int                 Unavailable ;  /* callback function possible? */
@@ -63,6 +72,7 @@
  /*
   remember mapped memory areas
  */
+ ADAPTER_MEMORY     MappedMemory[MAX_MAPPED_ENTRIES] ;
  CARD_PROPERTIES     Properties ;
  dword               cardType ;
  dword               protocol_id ;       /* configured protocol identifier */
@@ -87,15 +97,15 @@
  dword               downloadAddrTable[4] ; /* add. for MultiMaster */
  dword               MemoryBase ;
  dword               MemorySize ;
- byte       *Address ;
+ byte                *Address ;
  byte                *Config ;
  byte                *Control ;
- byte       *reset ;
- byte       *port ;
- byte       *ram ;
- byte       *cfg ;
- byte       *prom ;
- byte       *ctlReg ;
+ byte                *reset ;
+ byte                *port ;
+ byte                *ram ;
+ byte                *cfg ;
+ byte                *prom ;
+ byte                *ctlReg ;
  struct pc_maint  *pcm ;
  diva_os_dependent_devica_name_t os_name;
  byte                Name[32] ;
@@ -105,6 +115,7 @@
  char               *ProtocolSuffix ; /* internal protocolfile table */
  char                Archive[32] ;
  char                Protocol[32] ;
+ char                AddDownload[32] ; /* Dsp- or other additional download files */
  char                Oad1[ISDN_MAX_NUM_LEN] ;
  char                Osa1[ISDN_MAX_NUM_LEN] ;
  char                Oad2[ISDN_MAX_NUM_LEN] ;
@@ -153,8 +164,26 @@
  byte                ModemCarrierWaitTimeSec;
  byte                ModemCarrierLossWaitTimeTenthSec;
  byte                PiafsLinkTurnaroundInFrames;
+ byte                DiscAfterProgress;
+ byte                AniDniLimiter[3];
+ byte                TxAttenuation;  /* PRI/E1 only: attenuate TX signal */
  word                QsigFeatures;
  dword               GenerateRingtone ;
+ dword               SupplementaryServicesFeatures;
+ dword               R2Dialect;
+ dword               R2CasOptions;
+ dword               FaxV34Options;
+ dword               DisabledDspMask;
+ dword               AdapterTestMask;
+ dword               DspImageLength;
+ word                AlertToIn20mSecTicks;
+ word                ModemEyeSetup;
+ byte                R2CtryLength;
+ byte                CCBSRelTimer;
+ byte               *PcCfgBufferFile;/* flexible parameter via file */
+ byte               *PcCfgBuffer ; /* flexible parameter via multistring */
+ diva_os_dump_file_t dump_file; /* dump memory to file at lowest irq level */
+ diva_os_board_trace_t board_trace ; /* traces from the board */
  diva_os_spin_lock_t isr_spin_lock;
  diva_os_spin_lock_t data_spin_lock;
  diva_os_soft_isr_t req_soft_isr;
@@ -180,15 +209,21 @@
  void        (* stop)(PISDN_ADAPTER) ;
  void        (* rstFnc)(PISDN_ADAPTER) ;
  void        (* trapFnc)(PISDN_ADAPTER) ;
+ dword            (* DetectDsps)(PISDN_ADAPTER) ;
  void        (* os_trap_nfy_Fnc)(PISDN_ADAPTER, dword) ;
  diva_os_isr_callback_t diva_isr_handler;
- dword               sdram_bar;
+ dword               sdram_bar;  /* must be 32 bit */
  dword               fpga_features;
  volatile int        pcm_pending;
- volatile unsigned long      pcm_data;
+ volatile void *     pcm_data;
  diva_xdi_capi_cfg_t capi_cfg;
  dword               tasks;
- void*               dma_map;
+ void               *dma_map;
+ int             (*DivaAdapterTestProc)(PISDN_ADAPTER);
+ void               *AdapterTestMemoryStart;
+ dword               AdapterTestMemoryLength;
+ const byte* cfg_lib_memory_init;
+ dword       cfg_lib_memory_init_length;
 };
 /* ---------------------------------------------------------------------
   Entity table
@@ -219,8 +254,8 @@
 /* ---------------------------------------------------------------------
   Functions for port io
    --------------------------------------------------------------------- */
-void outp_words_from_buffer (word* adr, byte* P, word len);
-void inp_words_to_buffer  (word* adr, byte* P, word len);
+void outp_words_from_buffer (word* adr, byte* P, dword len);
+void inp_words_to_buffer    (word* adr, byte* P, dword len);
 /* ---------------------------------------------------------------------
   platform specific conversions
    --------------------------------------------------------------------- */
@@ -240,6 +275,10 @@
 void io_outw(ADAPTER * a, void * adr, word data);
 void io_out_buffer(ADAPTER * a, void * adr, void * P, word length);
 void io_inc(ADAPTER * a, void * adr);
+void bri_in_buffer (PISDN_ADAPTER IoAdapter, dword Pos,
+                    void *Buf, dword Len);
+int bri_out_buffer (PISDN_ADAPTER IoAdapter, dword Pos,
+                    void *Buf, dword Len, int Verify);
 /* ---------------------------------------------------------------------
   ram access functions for memory mapped cards
    --------------------------------------------------------------------- */
diff -Nru a/drivers/isdn/hardware/eicon/maintidi.c b/drivers/isdn/hardware/eicon/maintidi.c
--- a/drivers/isdn/hardware/eicon/maintidi.c	2004-07-12 01:01:03 -07:00
+++ b/drivers/isdn/hardware/eicon/maintidi.c	2004-08-28 13:14:29 -07:00
@@ -115,7 +115,7 @@
 		return NULL;
 	}
 
-  pmem += sizeof(*pLib);
+	pmem += sizeof(*pLib);
 	memset(pLib, 0x00, sizeof(*pLib));
 
 	pLib->Adapter  = Adapter;
@@ -337,13 +337,60 @@
         pLib->e.RNum       = 1;
         pLib->e.R->P       = (byte*)&pLib->buffer[0];
         pLib->e.R->PLength = (word)(sizeof(pLib->buffer) - 1);
+
       } else {
         /*
           Indication reception complete, process it now
           */
         byte* p = (byte*)&pLib->buffer[0];
         pLib->buffer[pLib->e.R->PLength] = 0; /* terminate I.E. with zero */
+
         switch (Ind) {
+          case MAN_COMBI_IND: {
+            int total_length    = pLib->e.R->PLength;
+            word  this_ind_length;
+
+            while (total_length > 3 && *p) {
+              Ind = *p++;
+              this_ind_length = (word)p[0] | ((word)p[1] << 8);
+              p += 2;
+
+              switch (Ind) {
+                case MAN_INFO_IND:
+                  if (process_idi_info (pLib, (diva_man_var_header_t*)p)) {
+                    return (-1);
+                  }
+                  break;
+      					case MAN_EVENT_IND:
+                  if (process_idi_event (pLib, (diva_man_var_header_t*)p)) {
+                    return (-1);
+                  }
+                  break;
+                case MAN_TRACE_IND:
+                  if (pLib->trace_on == 1) {
+                    /*
+                      Ignore first trace event that is result of
+                      EVENT_ON operation
+                    */
+                    pLib->trace_on++;
+                  } else {
+                    /*
+                      Delivery XLOG buffer to application
+                      */
+                    if (pLib->user_proc_table.trace_proc) {
+                      (*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context,
+                                                            &pLib->instance, pLib->Adapter,
+                                                            p, this_ind_length);
+                    }
+                  }
+                  break;
+                default:
+                  diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind (DMA mode): %02x", Ind);
+              }
+              p += (this_ind_length+1);
+              total_length -= (4 + this_ind_length);
+            }
+          } break;
           case MAN_INFO_IND:
             if (process_idi_info (pLib, (diva_man_var_header_t*)p)) {
               return (-1);
@@ -806,7 +853,7 @@
 }
 
 static int process_idi_event (diva_strace_context_t* pLib,
-															diva_man_var_header_t* pVar) {
+				diva_man_var_header_t* pVar) {
 	const char* path = (char*)&pVar->path_length+1;
 	char name[64];
 	int i;
diff -Nru a/drivers/isdn/hardware/eicon/maintidi.h b/drivers/isdn/hardware/eicon/maintidi.h
--- a/drivers/isdn/hardware/eicon/maintidi.h	2002-10-10 20:09:04 -07:00
+++ b/drivers/isdn/hardware/eicon/maintidi.h	2004-08-28 13:14:29 -07:00
@@ -49,6 +49,8 @@
 	void*							 variable; /* Variable that will receive value */
 } diva_strace_path2action_t;
 
+#define DIVA_MAX_MANAGEMENT_TRANSFER_SIZE 4096
+
 typedef struct _diva_strace_context {
 	diva_strace_library_interface_t	instance;
 
@@ -62,7 +64,7 @@
   IDI_CALL request;
   BUFFERS  XData;
   BUFFERS  RData;
-	byte buffer[2048+512+1];
+	byte buffer[DIVA_MAX_MANAGEMENT_TRANSFER_SIZE + 1];
   int removal_state;
   int general_b_ch_event;
   int general_fax_event;
diff -Nru a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c
--- a/drivers/isdn/hardware/eicon/mntfunc.c	2004-07-12 01:01:12 -07:00
+++ b/drivers/isdn/hardware/eicon/mntfunc.c	2004-08-28 13:14:30 -07:00
@@ -1,4 +1,4 @@
-/* $Id: mntfunc.c,v 1.19 2004/01/09 21:22:03 armin Exp $
+/* $Id: mntfunc.c,v 1.19.6.2 2004/08/28 20:03:53 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * Maint module
@@ -23,17 +23,12 @@
 
 extern void DIVA_DIDD_Read(void *, int);
 
-#define MAX_DESCRIPTORS  32
-
 static dword notify_handle;
 static DESCRIPTOR DAdapter;
 static DESCRIPTOR MAdapter;
 static DESCRIPTOR MaintDescriptor =
     { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
 
-extern void *diva_os_malloc_tbuffer(unsigned long flags,
-				    unsigned long size);
-extern void diva_os_free_tbuffer(unsigned long flags, void *ptr);
 extern int diva_os_copy_to_user(void *os_handle, void __user *dst,
 				const void *src, int length);
 extern int diva_os_copy_from_user(void *os_handle, void *dst,
@@ -47,16 +42,6 @@
 #include "debuglib.c"
 
 /*
- * stop debug
- */
-static void stop_dbg(void)
-{
-	DbgDeregister();
-	memset(&MAdapter, 0, sizeof(MAdapter));
-	dprintf = no_printf;
-}
-
-/*
  *  DIDD callback function
  */
 static void *didd_callback(void *context, DESCRIPTOR * adapter,
@@ -66,7 +51,9 @@
 		DBG_ERR(("cb: Change in DAdapter ? Oops ?."));
 	} else if (adapter->type == IDI_DIMAINT) {
 		if (removal) {
-			stop_dbg();
+			DbgDeregister();
+			memset(&MAdapter, 0, sizeof(MAdapter));
+			dprintf = no_printf;
 		} else {
 			memcpy(&MAdapter, adapter, sizeof(MAdapter));
 			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
@@ -131,8 +118,6 @@
 {
 	IDI_SYNC_REQ req;
 
-	stop_dbg();
-
 	req.didd_notify.e.Req = 0;
 	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
 	req.didd_notify.info.handle = notify_handle;
@@ -193,34 +178,63 @@
 		}
 		break;
 
+    /*
+       Filter commands will ignore the ID due to fact that filtering affects
+       the B- channel and Audio Tap trace levels only. Also MAINT driver will
+       select the right trace ID by itself
+       */
+	case DITRACE_WRITE_SELECTIVE_TRACE_FILTER:
+		if (!mask) {
+			ret = diva_set_trace_filter (1, "*");
+		} else if (mask < sizeof(data)) {
+			if (copy_from_user((void *)&data[0], (void *)(((byte*)buf)+12), mask)) {
+				ret = -EFAULT;
+			} else {
+				ret = diva_set_trace_filter ((int)mask, data);
+			}
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+
+	case DITRACE_READ_SELECTIVE_TRACE_FILTER:
+		if ((ret = diva_get_trace_filter (sizeof(data), data)) > 0) {
+			if (copy_to_user ((void*)buf, (void*)&data[0], ret))
+				ret = -EFAULT;
+		} else {
+			ret = -ENODEV;
+		}
+		break;
+
 	case DITRACE_READ_TRACE_ENTRY:{
 			diva_os_spin_lock_magic_t old_irql;
 			word size;
 			diva_dbg_entry_head_t *pmsg;
 			byte *pbuf;
 
-			if ((pmsg = diva_maint_get_message(&size, &old_irql))) {
+			if (!(pbuf = diva_os_malloc(0, mask))) {
+				return (-ENOMEM);
+			}
+
+			for(;;) {
+				if (!(pmsg =
+				    diva_maint_get_message(&size, &old_irql))) {
+					break;
+				}
 				if (size > mask) {
 					diva_maint_ack_message(0, &old_irql);
 					ret = -EINVAL;
-				} else {
-					if (!(pbuf = diva_os_malloc_tbuffer(0, size)))
-					{
-						diva_maint_ack_message(0, &old_irql);
-						ret = -ENOMEM;
-					} else {
-						ret = size;
-						memcpy(pbuf, pmsg, size);
-						diva_maint_ack_message(1, &old_irql);
-						if ((count < size) || diva_os_copy_to_user (NULL, buf,
-						     (void *) pbuf, size))
-							ret = -EFAULT;
-						diva_os_free_tbuffer(0, pbuf);
-					}
+					break;
 				}
-			} else {
-				ret = 0;
+				ret = size;
+				memcpy(pbuf, pmsg, size);
+				diva_maint_ack_message(1, &old_irql);
+				if ((count < size) ||
+				     diva_os_copy_to_user (NULL, buf, (void *) pbuf, size))
+							ret = -EFAULT;
+				break;
 			}
+			diva_os_free(0, pbuf);
 		}
 		break;
 
@@ -235,7 +249,7 @@
 				ret = -EINVAL;
 				break;
 			}
-			if (!(pbuf = diva_os_malloc_tbuffer(0, mask))) {
+			if (!(pbuf = diva_os_malloc(0, mask))) {
 				return (-ENOMEM);
 			}
 
@@ -273,7 +287,7 @@
 			} else {
 				ret = written;
 			}
-			diva_os_free_tbuffer(0, pbuf);
+			diva_os_free(0, pbuf);
 		}
 		break;
 
@@ -302,7 +316,7 @@
 	} else {
 		while ((*buffer_length >= (64 * 1024))
 		       &&
-		       (!(*buffer = diva_os_malloc_tbuffer(0, *buffer_length)))) {
+		       (!(*buffer = diva_os_malloc (0, *buffer_length)))) {
 			*buffer_length -= 1024;
 		}
 
@@ -314,7 +328,7 @@
 
 	if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) {
 		if (!diva_dbg_mem) {
-			diva_os_free_tbuffer(0, *buffer);
+			diva_os_free (0, *buffer);
 		}
 		DBG_ERR(("init: maint init failed"));
 		return (0);
@@ -324,7 +338,7 @@
 		DBG_ERR(("init: failed to connect to DIDD."));
 		diva_maint_finit();
 		if (!diva_dbg_mem) {
-			diva_os_free_tbuffer(0, *buffer);
+			diva_os_free (0, *buffer);
 		}
 		return (0);
 	}
@@ -339,6 +353,8 @@
 	void *buffer;
 	int i = 100;
 
+	DbgDeregister();
+
 	while (diva_mnt_shutdown_xdi_adapters() && i--) {
 		diva_os_sleep(10);
 	}
@@ -346,6 +362,9 @@
 	disconnect_didd();
 
 	if ((buffer = diva_maint_finit())) {
-		diva_os_free_tbuffer(0, buffer);
+		diva_os_free (0, buffer);
 	}
+
+	memset(&MAdapter, 0, sizeof(MAdapter));
+	dprintf = no_printf;
 }
diff -Nru a/drivers/isdn/hardware/eicon/pc.h b/drivers/isdn/hardware/eicon/pc.h
--- a/drivers/isdn/hardware/eicon/pc.h	2002-10-10 20:09:06 -07:00
+++ b/drivers/isdn/hardware/eicon/pc.h	2004-08-28 13:14:30 -07:00
@@ -143,6 +143,7 @@
 #define N_DATA_ACK      12      /* data ack ind for D-bit procedure */
 #define N_EDATA_ACK     13      /* data ack ind for INTERRUPT       */
 #define N_XON           15      /* clear RNR state */
+#define N_COMBI_IND     N_XON   /* combined indication              */
 #define N_Q_BIT         0x10    /* Q-bit for req/ind                */
 #define N_M_BIT         0x20    /* M-bit for req/ind                */
 #define N_D_BIT         0x40    /* D-bit for req/ind                */
@@ -228,6 +229,10 @@
 #define VSWITCH_IND 66        /* capifunctions for D-CH-switching   */
 #define MWI_POLL 67     /* Message Waiting Status Request fkt */
 #define CALL_PEND_NOTIFY 68 /* notify capi to set new listen        */
+#define DO_NOTHING 69       /* dont do somethin if you get this     */
+#define INT_CT_REJ 70       /* ECT rejected internal command        */
+#define CALL_HOLD_COMPLETE 71 /* In NT Mode indicate hold complete  */
+#define CALL_RETRIEVE_COMPLETE 72 /* In NT Mode indicate retrieve complete  */
 /*------------------------------------------------------------------*/
 /* management service primitives                                    */
 /*------------------------------------------------------------------*/
@@ -241,6 +246,7 @@
 #define MAN_INFO_IND    2
 #define MAN_EVENT_IND   3
 #define MAN_TRACE_IND   4
+#define MAN_COMBI_IND   9
 #define MAN_ESC         0x80
 /*------------------------------------------------------------------*/
 /* return code coding                                               */
@@ -265,6 +271,7 @@
 /*------------------------------------------------------------------*/
 #define SHIFT 0x90              /* codeset shift                    */
 #define MORE 0xa0               /* more data                        */
+#define SDNCMPL 0xa1            /* sending complete                 */
 #define CL 0xb0                 /* congestion level                 */
         /* codeset 0                                                */
 #define SMSG 0x00               /* segmented message                */
@@ -288,6 +295,8 @@
 #define RDX 0x73                /* redirecting number extended      */
 #define RDN 0x74                /* redirecting number               */
 #define RIN 0x76                /* redirection number               */
+#define IUP 0x76                /* VN6 rerouter->PCS (codeset 6)    */
+#define IPU 0x77                /* VN6 PCS->rerouter (codeset 6)    */
 #define RI  0x79                /* restart indicator                */
 #define MIE 0x7a                /* management info element          */
 #define LLC 0x7c                /* low layer compatibility          */
@@ -296,6 +305,8 @@
 #define ESC 0x7f                /* escape extension                 */
 #define DLC 0x20                /* data link layer configuration    */
 #define NLC 0x21                /* network layer configuration      */
+#define REDIRECT_IE     0x22    /* redirection request/indication data */
+#define REDIRECT_NET_IE 0x23    /* redirection network override data   */
         /* codeset 6                                                */
 #define SIN 0x01                /* service indicator                */
 #define CIF 0x02                /* charging information             */
@@ -306,6 +317,7 @@
 /*------------------------------------------------------------------*/
 #define MSGTYPEIE        0x7a   /* Messagetype info element         */
 #define CRIE             0x7b   /* INFO info element                */
+#define CODESET6IE       0xec   /* Tunnel for Codeset 6 IEs         */
 #define VSWITCHIE        0xed   /* VSwitch info element             */
 #define SSEXTIE          0xee   /* Supplem. Service info element    */
 #define PROFILEIE        0xef   /* Profile info element             */
@@ -344,6 +356,13 @@
 #define CCBS_REQUEST              0x32
 #define CCBS_DEACTIVATE           0x33
 #define CCBS_INTERROGATE          0x34
+#define CCBS_STATUS               0x35
+#define CCBS_ERASE                0x36
+#define CCBS_B_FREE               0x37
+#define CCNR_INFO_RETAIN          0x38
+#define CCBS_REMOTE_USER_FREE     0x39
+#define CCNR_REQUEST              0x3a
+#define CCNR_INTERROGATE          0x3b
 #define GET_SUPPORTED_SERVICES    0xff
 #define DIVERSION_PROCEDURE_CFU     0x70
 #define DIVERSION_PROCEDURE_CFB     0x71
@@ -362,6 +381,7 @@
 #define SMASK_3PTY                 0x00000008
 #define SMASK_CALL_FORWARDING      0x00000010
 #define SMASK_CALL_DEFLECTION      0x00000020
+#define SMASK_MCID                 0x00000040
 #define SMASK_CCBS                 0x00000080
 #define SMASK_MWI                  0x00000100
 #define SMASK_CCNR                 0x00000200
@@ -406,6 +426,8 @@
 #define RTPL2_IN       13       /* RTP layer-2 protocol, incomming  */
 #define RTPL2          14       /* RTP layer-2 protocol             */
 #define V120_V42BIS    15       /* V.120 asynchronous mode supporting V.42bis compression */
+#define LISTENER       27       /* Layer 2 to listen line */
+#define MTP2           28       /* MTP2 Layer 2 */
 #define PIAFS_CRC      29       /* PIAFS Layer 2 with CRC calculation at L2 */
 /* ------------------------------------------------------
    PIAFS DLC DEFINITIONS
@@ -506,6 +528,22 @@
 |                     |      |                        data transfer.   |
 +---------------------+------+-----------------------------------------+
 */
+/* ------------------------------------------------------
+   LISTENER DLC DEFINITIONS
+   ------------------------------------------------------ */
+#define LISTENER_FEATURE_MASK_CUMMULATIVE            0x0001
+/* ------------------------------------------------------
+   LISTENER META-FRAME CODE/PRIMITIVE DEFINITIONS
+   ------------------------------------------------------ */
+#define META_CODE_LL_UDATA_RX 0x01
+#define META_CODE_LL_UDATA_TX 0x02
+#define META_CODE_LL_DATA_RX  0x03
+#define META_CODE_LL_DATA_TX  0x04
+#define META_CODE_LL_MDATA_RX 0x05
+#define META_CODE_LL_MDATA_TX 0x06
+#define META_CODE_EMPTY       0x10
+#define META_CODE_LOST_FRAMES 0x11
+#define META_FLAG_TRUNCATED   0x0001
 /*------------------------------------------------------------------*/
 /* CAPI-like profile to indicate features on LAW_REQ                */
 /*------------------------------------------------------------------*/
@@ -577,6 +615,14 @@
 #define MANUFACTURER_FEATURE_DMACONNECT           0x04000000L
 #define MANUFACTURER_FEATURE_AUDIO_TAP            0x08000000L
 #define MANUFACTURER_FEATURE_FAX_NONSTANDARD      0x10000000L
+#define MANUFACTURER_FEATURE_SS7                  0x20000000L
+#define MANUFACTURER_FEATURE_MADAPTER             0x40000000L
+#define MANUFACTURER_FEATURE_MEASURE              0x80000000L
+#define MANUFACTURER_FEATURE2_LISTENING           0x00000001L
+#define MANUFACTURER_FEATURE2_SS_DIFFCONTPOSSIBLE 0x00000002L
+#define MANUFACTURER_FEATURE2_GENERIC_TONE        0x00000004L
+#define MANUFACTURER_FEATURE2_COLOR_FAX           0x00000008L
+#define MANUFACTURER_FEATURE2_SS_ECT_DIFFCONTPOSSIBLE 0x00000010L
 #define RTP_PRIM_PAYLOAD_PCMU_8000     0
 #define RTP_PRIM_PAYLOAD_1016_8000     1
 #define RTP_PRIM_PAYLOAD_G726_32_8000  2
@@ -624,6 +670,15 @@
 #define VSINVOKEID    4
 #define VSCLMRKS       5
 #define VSTBCTIDENT    6
+#define VSETSILINKID   7
+#define VSSAMECONTROLLER 8
+/* Errorcodes for VSETSILINKID begin */
+#define VSETSILINKIDRRWC      1
+#define VSETSILINKIDREJECT    2
+#define VSETSILINKIDTIMEOUT   3
+#define VSETSILINKIDFAILCOUNT 4
+#define VSETSILINKIDERROR     5
+/* Errorcodes for VSETSILINKID end */
 /* -----------------------------------------------------------**
 ** The PROTOCOL_FEATURE_STRING in feature.h (included         **
 ** in prstart.sx and astart.sx) defines capabilities and      **
@@ -647,5 +702,37 @@
 #define PROTCAP_FREE13    0x2000  /* not used                            */
 #define PROTCAP_FREE14    0x4000  /* not used                            */
 #define PROTCAP_EXTENSION 0x8000  /* used for future extentions          */
+/* -----------------------------------------------------------* */
+/* Onhook data transmission ETS30065901 */
+/* Message Type */
+/*#define RESERVED4                 0x4*/
+#define CALL_SETUP                0x80
+#define MESSAGE_WAITING_INDICATOR 0x82
+/*#define RESERVED84                0x84*/
+/*#define RESERVED85                0x85*/
+#define ADVICE_OF_CHARGE          0x86
+/*1111 0001
+to
+1111 1111
+F1H - Reserved for network operator use
+to
+FFH*/
+/* Parameter Types */
+#define DATE_AND_TIME                                           1
+#define CLI_PARAMETER_TYPE                                      2
+#define CALLED_DIRECTORY_NUMBER_PARAMETER_TYPE                  3
+#define REASON_FOR_ABSENCE_OF_CLI_PARAMETER_TYPE                4
+#define NAME_PARAMETER_TYPE                                     7
+#define REASON_FOR_ABSENCE_OF_CALLING_PARTY_NAME_PARAMETER_TYPE 8
+#define VISUAL_INDICATOR_PARAMETER_TYPE                         0xb
+#define COMPLEMENTARY_CLI_PARAMETER_TYPE                        0x10
+#define CALL_TYPE_PARAMETER_TYPE                                0x11
+#define FIRST_CALLED_LINE_DIRECTORY_NUMBER_PARAMETER_TYPE       0x12
+#define NETWORK_MESSAGE_SYSTEM_STATUS_PARAMETER_TYPE            0x13
+#define FORWARDED_CALL_TYPE_PARAMETER_TYPE                      0x15
+#define TYPE_OF_CALLING_USER_PARAMETER_TYPE                     0x16
+#define REDIRECTING_NUMBER_PARAMETER_TYPE                       0x1a
+#define EXTENSION_FOR_NETWORK_OPERATOR_USE_PARAMETER_TYPE       0xe0
+/* -----------------------------------------------------------* */
 #else
 #endif /* PC_H_INCLUDED  } */
diff -Nru a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
--- a/drivers/isdn/hardware/eicon/platform.h	2004-08-02 03:56:11 -07:00
+++ b/drivers/isdn/hardware/eicon/platform.h	2004-08-28 13:14:30 -07:00
@@ -1,4 +1,4 @@
-/* $Id: platform.h,v 1.37.4.1 2004/07/28 14:47:21 armin Exp $
+/* $Id: platform.h,v 1.37.4.2 2004/08/28 20:03:53 armin Exp $
  *
  * platform.h
  * 
@@ -269,20 +269,6 @@
                               diva_os_spin_lock_magic_t* old_irql, \
                               void* dbg) { spin_unlock_bh(a); }
 
-static __inline__ void diva_os_enter_spin_lock_hard (diva_os_spin_lock_t* a, \
-                                   diva_os_spin_lock_magic_t* old_irql, \
-                                   void* dbg) { \
-  unsigned long flags; \
-  spin_lock_irqsave (a, flags); \
-  *old_irql = (diva_os_spin_lock_magic_t)flags; \
-}
-static __inline__ void diva_os_leave_spin_lock_hard (diva_os_spin_lock_t* a, \
-                                   diva_os_spin_lock_magic_t* old_irql, \
-                                   void* dbg) { \
-  unsigned long flags = (unsigned long)*old_irql; \
-	spin_unlock_irqrestore (a, flags); \
-}
-
 #define diva_os_destroy_spin_lock(a,b) do { } while(0)
 
 /*
@@ -347,12 +333,18 @@
 
 #define DIVA_IDI_RX_DMA 1
 
+/*
+** endian macros
+*/
 #define READ_WORD(addr)   readw(addr)
 #define READ_DWORD(addr)  readl(addr)
 
 #define WRITE_WORD(addr,v)  writew(v,addr)
 #define WRITE_DWORD(addr,v) writel(v,addr)
 
+/*
+** 32/64 bit macors
+*/
 #ifdef BITS_PER_LONG
  #if BITS_PER_LONG > 32 
   #define PLATFORM_GT_32BIT
@@ -360,8 +352,23 @@
  #endif
 #endif
 
+/*
+** undef os definitions of macros we use
+*/
 #undef ID_MASK
 #undef N_DATA
 #undef ADDR
+
+/*
+** dump file
+*/
+#define diva_os_dump_file_t char
+#define diva_os_board_trace_t char
+#define diva_os_dump_file(__x__) do { } while(0)
+
+/*
+** size of internal arrays
+*/
+#define MAX_DESCRIPTORS 64
 
 #endif	/* __PLATFORM_H__ */
diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
--- a/drivers/isdn/hisax/avm_pci.c	2004-07-28 21:58:45 -07:00
+++ b/drivers/isdn/hisax/avm_pci.c	2004-08-24 02:08:30 -07:00
@@ -752,70 +752,70 @@
 		cs->hw.avm.cfg_reg = card->para[1];
 		cs->irq = card->para[0];
 		cs->subtyp = AVM_FRITZ_PNP;
-	} else {
+		goto ready;
+	}
 #ifdef __ISAPNP__
-		if (isapnp_present()) {
-			struct pnp_dev *pnp_avm_d = NULL;
-			if ((pnp_avm_c = pnp_find_card(
+	if (isapnp_present()) {
+		struct pnp_dev *pnp_avm_d = NULL;
+		if ((pnp_avm_c = pnp_find_card(
+			ISAPNP_VENDOR('A', 'V', 'M'),
+			ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
+			if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
 				ISAPNP_VENDOR('A', 'V', 'M'),
-				ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
-				if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
-					ISAPNP_VENDOR('A', 'V', 'M'),
-					ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
-					int err;
+				ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
+				int err;
 
-					pnp_disable_dev(pnp_avm_d);
-					err = pnp_activate_dev(pnp_avm_d);
-					if (err<0) {
-						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
-							__FUNCTION__, err);
-						return(0);
-					}
-					cs->hw.avm.cfg_reg =
-						pnp_port_start(pnp_avm_d, 0);
-					cs->irq = pnp_irq(pnp_avm_d, 0);
-					if (!cs->irq) {
-						printk(KERN_ERR "FritzPnP:No IRQ\n");
-						return(0);
-					}
-					if (!cs->hw.avm.cfg_reg) {
-						printk(KERN_ERR "FritzPnP:No IO address\n");
-						return(0);
-					}
-					cs->subtyp = AVM_FRITZ_PNP;
-					goto ready;
+				pnp_disable_dev(pnp_avm_d);
+				err = pnp_activate_dev(pnp_avm_d);
+				if (err<0) {
+					printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+						__FUNCTION__, err);
+					return(0);
+				}
+				cs->hw.avm.cfg_reg =
+					pnp_port_start(pnp_avm_d, 0);
+				cs->irq = pnp_irq(pnp_avm_d, 0);
+				if (!cs->irq) {
+					printk(KERN_ERR "FritzPnP:No IRQ\n");
+					return(0);
+				}
+				if (!cs->hw.avm.cfg_reg) {
+					printk(KERN_ERR "FritzPnP:No IO address\n");
+					return(0);
 				}
+				cs->subtyp = AVM_FRITZ_PNP;
+				goto ready;
 			}
-		} else {
-			printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
 		}
+	} else {
+		printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
+	}
 #endif
 #ifdef CONFIG_PCI
-		if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
-			PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
-			cs->irq = dev_avm->irq;
-			if (!cs->irq) {
-				printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			if (pci_enable_device(dev_avm))
-				return(0);
-			cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
-			if (!cs->hw.avm.cfg_reg) {
-				printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = AVM_FRITZ_PCI;
-		} else {
-			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+	if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
+		PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
+		cs->irq = dev_avm->irq;
+		if (!cs->irq) {
+			printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
+			return(0);
+		}
+		if (pci_enable_device(dev_avm))
+			return(0);
+		cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
+		if (!cs->hw.avm.cfg_reg) {
+			printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
 			return(0);
 		}
-		cs->irq_flags |= SA_SHIRQ;
+		cs->subtyp = AVM_FRITZ_PCI;
+	} else {
+		printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+		return(0);
+	}
+	cs->irq_flags |= SA_SHIRQ;
 #else
-		printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
-		return (0);
+	printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
+	return (0);
 #endif /* CONFIG_PCI */
-	}
 ready:
 	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
 	if (!request_region(cs->hw.avm.cfg_reg, 32,
diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
--- a/drivers/isdn/hisax/bkm_a4t.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hisax/bkm_a4t.c	2004-08-27 00:02:36 -07:00
@@ -265,7 +265,7 @@
 	char tmp[64];
 	u_int pci_memaddr = 0, found = 0;
 	I20_REGISTER_FILE *pI20_Regs;
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #endif
 
 	strcpy(tmp, bkm_a4t_revision);
@@ -275,7 +275,7 @@
 	} else
 		return (0);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
 		PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
 		u16 sub_sys;
diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
--- a/drivers/isdn/hisax/bkm_a8.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hisax/bkm_a8.c	2004-08-27 00:02:36 -07:00
@@ -21,7 +21,7 @@
 #include <linux/pci.h>
 #include "bkm_ax.h"
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 #define	ATTEMPT_PCI_REMAPPING	/* Required for PLX rev 1 */
 
@@ -285,7 +285,7 @@
 int __init
 setup_sct_quadro(struct IsdnCard *card)
 {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u_char pci_rev_id;
diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
--- a/drivers/isdn/hisax/diva.c	2004-08-02 01:00:45 -07:00
+++ b/drivers/isdn/hisax/diva.c	2004-08-27 00:02:36 -07:00
@@ -1027,7 +1027,7 @@
 			}
 		}
 #endif
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		cs->subtyp = 0;
 		if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
 			PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
--- a/drivers/isdn/hisax/elsa.c	2004-08-02 01:00:45 -07:00
+++ b/drivers/isdn/hisax/elsa.c	2004-08-27 00:02:36 -07:00
@@ -1022,7 +1022,7 @@
 		       cs->hw.elsa.base,
 		       cs->irq);
 	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		cs->subtyp = 0;
 		if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
--- a/drivers/isdn/hisax/enternow_pci.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hisax/enternow_pci.c	2004-08-27 00:02:36 -07:00
@@ -299,7 +299,7 @@
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
--- a/drivers/isdn/hisax/gazel.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hisax/gazel.c	2004-08-27 00:02:36 -07:00
@@ -634,7 +634,7 @@
 			return (0);
 	} else {
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		if (setup_gazelpci(cs))
 			return (0);
 #else
diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
--- a/drivers/isdn/hisax/hfc_pci.c	2004-08-02 01:00:45 -07:00
+++ b/drivers/isdn/hisax/hfc_pci.c	2004-08-27 00:02:36 -07:00
@@ -65,7 +65,7 @@
 };
 
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 /******************************************/
 /* free hardware resources used by driver */
@@ -1655,7 +1655,7 @@
 #endif
 	strcpy(tmp, hfcpci_revision);
 	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	cs->hw.hfcpci.int_s1 = 0;
 	cs->dc.hfcpci.ph_state = 0;
 	cs->hw.hfcpci.fifo = 255;
diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
--- a/drivers/isdn/hisax/niccy.c	2004-03-31 05:35:08 -08:00
+++ b/drivers/isdn/hisax/niccy.c	2004-08-27 00:02:36 -07:00
@@ -309,7 +309,7 @@
 			return (0);
 		}
 	} else {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		u_int pci_ioaddr;
 		cs->subtyp = 0;
 		if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
--- a/drivers/isdn/hisax/nj_s.c	2004-06-12 20:52:27 -07:00
+++ b/drivers/isdn/hisax/nj_s.c	2004-08-27 00:02:36 -07:00
@@ -167,7 +167,7 @@
 		return(0);
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 	for ( ;; )
 	{
diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
--- a/drivers/isdn/hisax/nj_u.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hisax/nj_u.c	2004-08-27 00:02:36 -07:00
@@ -137,7 +137,7 @@
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #endif
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
@@ -148,7 +148,7 @@
 		return(0);
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 	for ( ;; )
 	{
diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
--- a/drivers/isdn/hisax/sedlbauer.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hisax/sedlbauer.c	2004-08-27 00:02:36 -07:00
@@ -618,7 +618,7 @@
 		}
 #endif
 /* Probe for Sedlbauer speed pci */
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
 				PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
 			if (pci_enable_device(dev_sedl))
diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
--- a/drivers/isdn/hisax/telespci.c	2004-02-18 19:42:12 -08:00
+++ b/drivers/isdn/hisax/telespci.c	2004-08-27 00:02:36 -07:00
@@ -300,7 +300,7 @@
 	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_TELESPCI)
 		return (0);
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
 		if (pci_enable_device(dev_tel))
 			return(0);
diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
--- a/drivers/isdn/hisax/w6692.c	2004-02-18 19:42:19 -08:00
+++ b/drivers/isdn/hisax/w6692.c	2004-08-27 00:02:36 -07:00
@@ -1012,7 +1012,7 @@
 	printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_W6692)
 		return (0);
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	while (id_list[id_idx].vendor_id) {
 		dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,
 					    id_list[id_idx].device_id,
diff -Nru a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c
--- a/drivers/isdn/tpam/tpam_main.c	2003-07-31 08:59:04 -07:00
+++ b/drivers/isdn/tpam/tpam_main.c	2004-08-24 02:08:33 -07:00
@@ -23,7 +23,7 @@
 
 /* Local functions prototypes */
 static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit tpam_unregister_card(tpam_card *);
+static void __devexit tpam_unregister_card(struct pci_dev *, tpam_card *);
 static void __devexit tpam_remove(struct pci_dev *);
 static int __init tpam_init(void);
 static void __exit tpam_exit(void);
@@ -86,13 +86,20 @@
  */
 static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) {
 	tpam_card *card, *c;
-	int i;
+	int i, err;
+
+	if (pci_enable_device(dev)) {
+		printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n",
+			pci_name(dev));
+		return -ENODEV;
+	}
 
 	/* allocate memory for the board structure */
 	if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) {
 		printk(KERN_ERR "TurboPAM: tpam_register_card: "
 		       "kmalloc failed!\n");
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_out_disable_dev;
 	}
 
 	memset((char *)card, 0, sizeof(tpam_card));
@@ -106,8 +113,8 @@
 			card->interface.id, card)) {
 		printk(KERN_ERR "TurboPAM: tpam_register_card: "
 		       "could not request irq %d\n", card->irq);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_free_card;
 	}
 
 	/* remap board memory */
@@ -115,9 +122,8 @@
 						   0x800000))) {
 		printk(KERN_ERR "TurboPAM: tpam_register_card: "
 		       "unable to remap bar0\n");
-		free_irq(card->irq, card);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_free_irq;
 	}
 
 	/* reset the board */
@@ -150,10 +156,8 @@
 	if (!register_isdn(&card->interface)) {
 		printk(KERN_ERR "TurboPAM: tpam_register_card: "
 		       "unable to register %s\n", card->interface.id);
-		free_irq(card->irq, card);
-		iounmap((void *)card->bar0);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_iounmap;
 	}
 	card->id = card->interface.channels;
 
@@ -195,6 +199,19 @@
 	pci_set_drvdata(dev, card);
 
 	return 0;
+
+err_out_iounmap:
+	iounmap((void *)card->bar0);
+
+err_out_free_irq:
+	free_irq(card->irq, card);
+
+err_out_free_card:
+	kfree(card);
+
+err_out_disable_dev:
+	pci_disable_device(dev);
+	return err;
 }
 
 /*
@@ -202,7 +219,7 @@
  *
  * 	card: the board.
  */
-static void __devexit tpam_unregister_card(tpam_card *card) {
+static void __devexit tpam_unregister_card(struct pci_dev *pcidev, tpam_card *card) {
 	isdn_ctrl cmd;
 
 	/* prevent the ISDN link layer that the driver will be unloaded */
@@ -215,6 +232,8 @@
 
 	/* release mapped memory */
 	iounmap((void *)card->bar0);
+
+	pci_disable_device(pcidev);
 }
 
 /*
@@ -235,7 +254,7 @@
 	}
 	
 	/* unregister each board */
-	tpam_unregister_card(card);
+	tpam_unregister_card(pcidev, card);
 	
 	/* and free the board structure itself */
 	kfree(card);
diff -Nru a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
--- a/drivers/macintosh/adbhid.c	2004-07-26 14:25:37 -07:00
+++ b/drivers/macintosh/adbhid.c	2004-03-10 14:41:34 -08:00
@@ -326,7 +326,7 @@
 	input_report_key(&adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));
 	input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
 
-	if (nb >= 4)
+	if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD)
 		input_report_key(&adbhid[id]->input, BTN_RIGHT,  !((data[3] >> 7) & 1));
 
 	input_report_rel(&adbhid[id]->input, REL_X,
diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig
--- a/drivers/md/Kconfig	2004-06-17 23:53:43 -07:00
+++ b/drivers/md/Kconfig	2004-08-24 02:08:45 -07:00
@@ -85,6 +85,24 @@
 
 	  If unsure, say Y.
 
+config MD_RAID10
+	tristate "RAID-10 (mirrored striping) mode (EXPERIMENTAL)"
+	depends on BLK_DEV_MD && EXPERIMENTAL
+	---help---
+	  RAID-10 provides a combination of striping (RAID-0) and
+	  mirroring (RAID-1) with easier configuration and more flexable
+	  layout.
+	  Unlike RAID-0, but like RAID-1, RAID-10 requires all devices to
+	  be the same size (or atleast, only as much as the smallest device
+	  will be used).
+	  RAID-10 provides a variety of layouts that provide different levels
+	  of redundancy and performance.
+
+	  RAID-10 requires mdadm-1.7.0 or later, available at:
+
+	  ftp://ftp.kernel.org/pub/linux/utils/raid/mdadm/
+
+
 config MD_RAID5
 	tristate "RAID-4/RAID-5 mode"
 	depends on BLK_DEV_MD
diff -Nru a/drivers/md/Makefile b/drivers/md/Makefile
--- a/drivers/md/Makefile	2004-08-10 12:42:40 -07:00
+++ b/drivers/md/Makefile	2004-08-24 02:08:45 -07:00
@@ -20,6 +20,7 @@
 obj-$(CONFIG_MD_LINEAR)		+= linear.o
 obj-$(CONFIG_MD_RAID0)		+= raid0.o
 obj-$(CONFIG_MD_RAID1)		+= raid1.o
+obj-$(CONFIG_MD_RAID10)		+= raid10.o
 obj-$(CONFIG_MD_RAID5)		+= raid5.o xor.o
 obj-$(CONFIG_MD_RAID6)		+= raid6.o xor.o
 obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	2004-08-23 01:14:46 -07:00
+++ b/drivers/md/md.c	2004-08-26 23:30:29 -07:00
@@ -406,7 +406,7 @@
 	return 0;
 
 fail:
-	printk(KERN_ERR "md: disabled device %s, could not read superblock.\n",
+	printk(KERN_WARNING "md: disabled device %s, could not read superblock.\n",
 		bdevname(rdev->bdev,b));
 	return -EINVAL;
 }
@@ -472,6 +472,31 @@
 	return csum;
 }
 
+/* csum_partial is not consistent between different architectures.
+ * Some (i386) do a 32bit csum.  Some (alpha) do 16 bit.
+ * This makes it hard for user-space to know what to do.
+ * So we use calc_sb_csum to set the checksum to allow working
+ * with older kernels, but allow calc_sb_csum_common to
+ * be used when checking if a checksum is correct, to
+ * make life easier for user-space tools that might write
+ * a superblock.
+ */
+static unsigned int calc_sb_csum_common(mdp_super_t *super)
+{
+	unsigned int  disk_csum = super->sb_csum;
+	unsigned long long newcsum = 0;
+	unsigned int csum;
+	int i;
+	unsigned int *superc = (int*) super;
+	super->sb_csum = 0;
+
+	for (i=0; i<MD_SB_BYTES/4; i++)
+		newcsum+= superc[i];
+	csum = (newcsum& 0xffffffff) + (newcsum>>32);
+	super->sb_csum = disk_csum;
+	return csum;
+}
+
 /*
  * Handle superblock details.
  * We want to be able to handle multiple superblock formats
@@ -554,7 +579,8 @@
 	if (sb->raid_disks <= 0)
 		goto abort;
 
-	if (calc_sb_csum(sb) != sb->sb_csum) {
+	if (calc_sb_csum(sb) != sb->sb_csum &&
+		calc_sb_csum_common(sb) != sb->sb_csum) {
 		printk(KERN_WARNING "md: invalid superblock checksum on %s\n",
 			b);
 		goto abort;
@@ -778,11 +804,21 @@
 static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
 {
 	unsigned int disk_csum, csum;
+	unsigned long long newcsum;
 	int size = 256 + sb->max_dev*2;
+	unsigned int *isuper = (unsigned int*)sb;
+	int i;
 
 	disk_csum = sb->sb_csum;
 	sb->sb_csum = 0;
-	csum = csum_partial((void *)sb, size, 0);
+	newcsum = 0;
+	for (i=0; size>=4; size -= 4 )
+		newcsum += le32_to_cpu(*isuper++);
+
+	if (size == 2)
+		newcsum += le16_to_cpu(*(unsigned short*) isuper);
+
+	csum = (newcsum & 0xffffffff) + (newcsum >> 32);
 	sb->sb_csum = disk_csum;
 	return csum;
 }
@@ -1075,20 +1111,24 @@
 /*
  * prevent the device from being mounted, repartitioned or
  * otherwise reused by a RAID array (or any other kernel
- * subsystem), by opening the device. [simply getting an
- * inode is not enough, the SCSI module usage code needs
- * an explicit open() on the device]
+ * subsystem), by bd_claiming the device.
  */
 static int lock_rdev(mdk_rdev_t *rdev, dev_t dev)
 {
 	int err = 0;
 	struct block_device *bdev;
+	char b[BDEVNAME_SIZE];
 
 	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
-	if (IS_ERR(bdev))
+	if (IS_ERR(bdev)) {
+		printk(KERN_ERR "md: could not open %s.\n",
+			__bdevname(dev, b));
 		return PTR_ERR(bdev);
+	}
 	err = bd_claim(bdev, rdev);
 	if (err) {
+		printk(KERN_ERR "md: could not bd_claim %s.\n",
+			bdevname(bdev, b));
 		blkdev_put(bdev);
 		return err;
 	}
@@ -1150,10 +1190,7 @@
 
 static void print_desc(mdp_disk_t *desc)
 {
-	char b[BDEVNAME_SIZE];
-
-	printk(" DISK<N:%d,%s(%d,%d),R:%d,S:%d>\n", desc->number,
-		__bdevname(MKDEV(desc->major, desc->minor), b),
+	printk(" DISK<N:%d,(%d,%d),R:%d,S:%d>\n", desc->number,
 		desc->major,desc->minor,desc->raid_disk,desc->state);
 }
 
@@ -1345,8 +1382,7 @@
 
 	rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
 	if (!rdev) {
-		printk(KERN_ERR "md: could not alloc mem for %s!\n", 
-			__bdevname(newdev, b));
+		printk(KERN_ERR "md: could not alloc mem for new device!\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	memset(rdev, 0, sizeof(*rdev));
@@ -1355,11 +1391,9 @@
 		goto abort_free;
 
 	err = lock_rdev(rdev, newdev);
-	if (err) {
-		printk(KERN_ERR "md: could not lock %s.\n",
-			__bdevname(newdev, b));
+	if (err)
 		goto abort_free;
-	}
+
 	rdev->desc_nr = -1;
 	rdev->faulty = 0;
 	rdev->in_sync = 0;
@@ -1648,6 +1682,8 @@
 	mddev->pers = pers[pnum];
 	spin_unlock(&pers_lock);
 
+	mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
+
 	err = mddev->pers->run(mddev);
 	if (err) {
 		printk(KERN_ERR "md: pers->run() failed ...\n");
@@ -1915,11 +1951,9 @@
 	mdk_rdev_t *start_rdev = NULL, *rdev;
 
 	start_rdev = md_import_device(startdev, 0, 0);
-	if (IS_ERR(start_rdev)) {
-		printk(KERN_WARNING "md: could not import %s!\n",
-			__bdevname(startdev, b));
+	if (IS_ERR(start_rdev))
 		return err;
-	}
+
 
 	/* NOTE: this can only work for 0.90.0 superblocks */
 	sb = (mdp_super_t*)page_address(start_rdev->sb_page);
@@ -1950,12 +1984,9 @@
 		if (MAJOR(dev) != desc->major || MINOR(dev) != desc->minor)
 			continue;
 		rdev = md_import_device(dev, 0, 0);
-		if (IS_ERR(rdev)) {
-			printk(KERN_WARNING "md: could not import %s,"
-				" trying to run array nevertheless.\n",
-				__bdevname(dev, b));
+		if (IS_ERR(rdev))
 			continue;
-		}
+
 		list_add(&rdev->same_set, &pending_raid_disks);
 	}
 
@@ -2187,42 +2218,6 @@
 	return 0;
 }
 
-static int hot_generate_error(mddev_t * mddev, dev_t dev)
-{
-	char b[BDEVNAME_SIZE];
-	struct request_queue *q;
-	mdk_rdev_t *rdev;
-
-	if (!mddev->pers)
-		return -ENODEV;
-
-	printk(KERN_INFO "md: trying to generate %s error in %s ... \n",
-		__bdevname(dev, b), mdname(mddev));
-
-	rdev = find_rdev(mddev, dev);
-	if (!rdev) {
-		/* MD_BUG(); */ /* like hell - it's not a driver bug */
-		return -ENXIO;
-	}
-
-	if (rdev->desc_nr == -1) {
-		MD_BUG();
-		return -EINVAL;
-	}
-	if (!rdev->in_sync)
-		return -ENODEV;
-
-	q = bdev_get_queue(rdev->bdev);
-	if (!q) {
-		MD_BUG();
-		return -ENODEV;
-	}
-	printk(KERN_INFO "md: okay, generating error!\n");
-//	q->oneshot_error = 1; // disabled for now
-
-	return 0;
-}
-
 static int hot_remove_disk(mddev_t * mddev, dev_t dev)
 {
 	char b[BDEVNAME_SIZE];
@@ -2231,9 +2226,6 @@
 	if (!mddev->pers)
 		return -ENODEV;
 
-	printk(KERN_INFO "md: trying to remove %s from %s ... \n",
-		__bdevname(dev, b), mdname(mddev));
-
 	rdev = find_rdev(mddev, dev);
 	if (!rdev)
 		return -ENXIO;
@@ -2261,9 +2253,6 @@
 	if (!mddev->pers)
 		return -ENODEV;
 
-	printk(KERN_INFO "md: trying to hot-add %s to %s ... \n",
-		__bdevname(dev, b), mdname(mddev));
-
 	if (mddev->major_version != 0) {
 		printk(KERN_WARNING "%s: HOT_ADD may only be used with"
 			" version-0 superblocks.\n",
@@ -2523,7 +2512,6 @@
 static int md_ioctl(struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	char b[BDEVNAME_SIZE];
 	int err = 0;
 	void __user *argp = (void __user *)arg;
 	struct hd_geometry __user *loc = argp;
@@ -2582,8 +2570,7 @@
 		}
 		err = autostart_array(new_decode_dev(arg));
 		if (err) {
-			printk(KERN_WARNING "md: autostart %s failed!\n",
-				__bdevname(arg, b));
+			printk(KERN_WARNING "md: autostart failed!\n");
 			goto abort;
 		}
 		goto done;
@@ -2724,9 +2711,7 @@
 				err = add_new_disk(mddev, &info);
 			goto done_unlock;
 		}
-		case HOT_GENERATE_ERROR:
-			err = hot_generate_error(mddev, new_decode_dev(arg));
-			goto done_unlock;
+
 		case HOT_REMOVE_DISK:
 			err = hot_remove_disk(mddev, new_decode_dev(arg));
 			goto done_unlock;
@@ -2953,6 +2938,7 @@
 	if (!mddev->pers->error_handler)
 		return;
 	mddev->pers->error_handler(mddev,rdev);
+	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
 }
@@ -2985,7 +2971,11 @@
 	unsigned long max_blocks, resync, res, dt, db, rt;
 
 	resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
-	max_blocks = mddev->size;
+
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+		max_blocks = mddev->resync_max_sectors >> 1;
+	else
+		max_blocks = mddev->size;
 
 	/*
 	 * Should not happen.
@@ -3221,11 +3211,6 @@
 	return 0;
 }
 
-void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors)
-{
-	rdev->bdev->bd_contains->bd_disk->sync_io += nr_sectors;
-}
-
 static int is_mddev_idle(mddev_t *mddev)
 {
 	mdk_rdev_t * rdev;
@@ -3238,8 +3223,12 @@
 		struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
 		curr_events = disk_stat_read(disk, read_sectors) + 
 				disk_stat_read(disk, write_sectors) - 
-				disk->sync_io;
-		if ((curr_events - rdev->last_events) > 32) {
+				atomic_read(&disk->sync_io);
+		/* Allow some slack between valud of curr_events and last_events,
+		 * as there are some uninteresting races.
+		 * Note: the following is an unsigned comparison.
+		 */
+		if ((curr_events - rdev->last_events + 32) > 64) {
 			rdev->last_events = curr_events;
 			idle = 0;
 		}
@@ -3373,7 +3362,14 @@
 		}
 	} while (mddev->curr_resync < 2);
 
-	max_sectors = mddev->size << 1;
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+		/* resync follows the size requested by the personality,
+		 * which default to physical size, but can be virtual size
+		 */
+		max_sectors = mddev->resync_max_sectors;
+	else
+		/* recovery follows the physical size of devices */
+		max_sectors = mddev->size << 1;
 
 	printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev));
 	printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:"
@@ -3731,7 +3727,6 @@
 
 static void autostart_arrays(int part)
 {
-	char b[BDEVNAME_SIZE];
 	mdk_rdev_t *rdev;
 	int i;
 
@@ -3741,11 +3736,9 @@
 		dev_t dev = detected_devices[i];
 
 		rdev = md_import_device(dev,0, 0);
-		if (IS_ERR(rdev)) {
-			printk(KERN_ALERT "md: could not import %s!\n",
-				__bdevname(dev, b));
+		if (IS_ERR(rdev))
 			continue;
-		}
+
 		if (rdev->faulty) {
 			MD_BUG();
 			continue;
@@ -3796,7 +3789,6 @@
 EXPORT_SYMBOL(register_md_personality);
 EXPORT_SYMBOL(unregister_md_personality);
 EXPORT_SYMBOL(md_error);
-EXPORT_SYMBOL(md_sync_acct);
 EXPORT_SYMBOL(md_done_sync);
 EXPORT_SYMBOL(md_write_start);
 EXPORT_SYMBOL(md_write_end);
diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c
--- a/drivers/md/raid1.c	2004-08-23 01:14:46 -07:00
+++ b/drivers/md/raid1.c	2004-08-24 02:08:45 -07:00
@@ -24,10 +24,6 @@
 
 #include <linux/raid/raid1.h>
 
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
-
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
  */
@@ -44,13 +40,12 @@
 {
 	struct pool_info *pi = data;
 	r1bio_t *r1_bio;
+	int size = offsetof(r1bio_t, bios[pi->raid_disks]);
 
 	/* allocate a r1bio with room for raid_disks entries in the bios array */
-	r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*pi->raid_disks,
-			 gfp_flags);
+	r1_bio = kmalloc(size, gfp_flags);
 	if (r1_bio)
-		memset(r1_bio, 0, sizeof(*r1_bio) +
-			       sizeof(struct bio*) * pi->raid_disks);
+		memset(r1_bio, 0, size);
 	else
 		unplug_slaves(pi->mddev);
 
@@ -104,7 +99,7 @@
 		bio->bi_io_vec[i].bv_page = page;
 	}
 
-	r1_bio->master_bio = bio;
+	r1_bio->master_bio = NULL;
 
 	return r1_bio;
 
@@ -189,32 +184,6 @@
 	spin_unlock_irqrestore(&conf->resync_lock, flags);
 }
 
-static int map(mddev_t *mddev, mdk_rdev_t **rdevp)
-{
-	conf_t *conf = mddev_to_conf(mddev);
-	int i, disks = conf->raid_disks;
-
-	/*
-	 * Later we do read balancing on the read side
-	 * now we use the first available disk.
-	 */
-
-	spin_lock_irq(&conf->device_lock);
-	for (i = 0; i < disks; i++) {
-		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
-		if (rdev && rdev->in_sync) {
-			*rdevp = rdev;
-			atomic_inc(&rdev->nr_pending);
-			spin_unlock_irq(&conf->device_lock);
-			return i;
-		}
-	}
-	spin_unlock_irq(&conf->device_lock);
-
-	printk(KERN_ERR "raid1_map(): huh, no more operational devices?\n");
-	return -1;
-}
-
 static void reschedule_retry(r1bio_t *r1_bio)
 {
 	unsigned long flags;
@@ -292,8 +261,9 @@
 		 * oops, read error:
 		 */
 		char b[BDEVNAME_SIZE];
-		printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n",
-		       bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
+		if (printk_ratelimit())
+			printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n",
+			       bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
 		reschedule_retry(r1_bio);
 	}
 
@@ -363,11 +333,11 @@
  *
  * The rdev for the device selected will have nr_pending incremented.
  */
-static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
+static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 {
 	const unsigned long this_sector = r1_bio->sector;
 	int new_disk = conf->last_used, disk = new_disk;
-	const int sectors = bio->bi_size >> 9;
+	const int sectors = r1_bio->sectors;
 	sector_t new_distance, current_distance;
 
 	spin_lock_irq(&conf->device_lock);
@@ -378,14 +348,14 @@
 	 */
 	if (conf->mddev->recovery_cp < MaxSector &&
 	    (this_sector + sectors >= conf->next_resync)) {
-		/* make sure that disk is operational */
+		/* Choose the first operation device, for consistancy */
 		new_disk = 0;
 
 		while (!conf->mirrors[new_disk].rdev ||
 		       !conf->mirrors[new_disk].rdev->in_sync) {
 			new_disk++;
 			if (new_disk == conf->raid_disks) {
-				new_disk = 0;
+				new_disk = -1;
 				break;
 			}
 		}
@@ -400,7 +370,7 @@
 			new_disk = conf->raid_disks;
 		new_disk--;
 		if (new_disk == disk) {
-			new_disk = conf->last_used;
+			new_disk = -1;
 			goto rb_out;
 		}
 	}
@@ -440,13 +410,13 @@
 	} while (disk != conf->last_used);
 
 rb_out:
-	r1_bio->read_disk = new_disk;
-	conf->next_seq_sect = this_sector + sectors;
 
-	conf->last_used = new_disk;
 
-	if (conf->mirrors[new_disk].rdev)
+	if (new_disk >= 0) {
+		conf->next_seq_sect = this_sector + sectors;
+		conf->last_used = new_disk;
 		atomic_inc(&conf->mirrors[new_disk].rdev->nr_pending);
+	}
 	spin_unlock_irq(&conf->device_lock);
 
 	return new_disk;
@@ -571,15 +541,26 @@
 	r1_bio->mddev = mddev;
 	r1_bio->sector = bio->bi_sector;
 
+	r1_bio->state = 0;
+
 	if (bio_data_dir(bio) == READ) {
 		/*
 		 * read balancing logic:
 		 */
-		mirror = conf->mirrors + read_balance(conf, bio, r1_bio);
+		int rdisk = read_balance(conf, r1_bio);
+
+		if (rdisk < 0) {
+			/* couldn't find anywhere to read from */
+			raid_end_bio_io(r1_bio);
+			return 0;
+		}
+		mirror = conf->mirrors + rdisk;
+
+		r1_bio->read_disk = rdisk;
 
 		read_bio = bio_clone(bio, GFP_NOIO);
 
-		r1_bio->bios[r1_bio->read_disk] = read_bio;
+		r1_bio->bios[rdisk] = read_bio;
 
 		read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset;
 		read_bio->bi_bdev = mirror->rdev->bdev;
@@ -903,7 +884,7 @@
 
 		atomic_inc(&conf->mirrors[i].rdev->nr_pending);
 		atomic_inc(&r1_bio->remaining);
-		md_sync_acct(conf->mirrors[i].rdev, wbio->bi_size >> 9);
+		md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
 		generic_make_request(wbio);
 	}
 
@@ -951,7 +932,7 @@
 		} else {
 			int disk;
 			bio = r1_bio->bios[r1_bio->read_disk];
-			if ((disk=map(mddev, &rdev)) == -1) {
+			if ((disk=read_balance(conf, r1_bio)) == -1) {
 				printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
 				       " read error for block %llu\n",
 				       bdevname(bio->bi_bdev,b),
@@ -961,10 +942,12 @@
 				r1_bio->bios[r1_bio->read_disk] = NULL;
 				r1_bio->read_disk = disk;
 				r1_bio->bios[r1_bio->read_disk] = bio;
-				printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
-				       " another mirror\n",
-				       bdevname(rdev->bdev,b),
-				       (unsigned long long)r1_bio->sector);
+				rdev = conf->mirrors[disk].rdev;
+				if (printk_ratelimit())
+					printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
+					       " another mirror\n",
+					       bdevname(rdev->bdev,b),
+					       (unsigned long long)r1_bio->sector);
 				bio->bi_bdev = rdev->bdev;
 				bio->bi_sector = r1_bio->sector + rdev->data_offset;
 				bio->bi_rw = READ;
@@ -1143,7 +1126,7 @@
 	bio = r1_bio->bios[disk];
 	r1_bio->sectors = nr_sectors;
 
-	md_sync_acct(mirror->rdev, nr_sectors);
+	md_sync_acct(mirror->rdev->bdev, nr_sectors);
 
 	generic_make_request(bio);
 
diff -Nru a/drivers/md/raid10.c b/drivers/md/raid10.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/raid10.c	2004-08-24 02:08:45 -07:00
@@ -0,0 +1,1780 @@
+/*
+ * raid10.c : Multiple Devices driver for Linux
+ *
+ * Copyright (C) 2000-2004 Neil Brown
+ *
+ * RAID-10 support for md.
+ *
+ * Base on code in raid1.c.  See raid1.c for futher copyright information.
+ *
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/raid/raid10.h>
+
+/*
+ * RAID10 provides a combination of RAID0 and RAID1 functionality.
+ * The layout of data is defined by
+ *    chunk_size
+ *    raid_disks
+ *    near_copies (stored in low byte of layout)
+ *    far_copies (stored in second byte of layout)
+ *
+ * The data to be stored is divided into chunks using chunksize.
+ * Each device is divided into far_copies sections.
+ * In each section, chunks are laid out in a style similar to raid0, but
+ * near_copies copies of each chunk is stored (each on a different drive).
+ * The starting device for each section is offset near_copies from the starting
+ * device of the previous section.
+ * Thus there are (near_copies*far_copies) of each chunk, and each is on a different
+ * drive.
+ * near_copies and far_copies must be at least one, and there product is at most
+ * raid_disks.
+ */
+
+/*
+ * Number of guaranteed r10bios in case of extreme VM load:
+ */
+#define	NR_RAID10_BIOS 256
+
+static void unplug_slaves(mddev_t *mddev);
+
+static void * r10bio_pool_alloc(int gfp_flags, void *data)
+{
+	conf_t *conf = data;
+	r10bio_t *r10_bio;
+	int size = offsetof(struct r10bio_s, devs[conf->copies]);
+
+	/* allocate a r10bio with room for raid_disks entries in the bios array */
+	r10_bio = kmalloc(size, gfp_flags);
+	if (r10_bio)
+		memset(r10_bio, 0, size);
+	else
+		unplug_slaves(conf->mddev);
+
+	return r10_bio;
+}
+
+static void r10bio_pool_free(void *r10_bio, void *data)
+{
+	kfree(r10_bio);
+}
+
+#define RESYNC_BLOCK_SIZE (64*1024)
+//#define RESYNC_BLOCK_SIZE PAGE_SIZE
+#define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9)
+#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
+#define RESYNC_WINDOW (2048*1024)
+
+/*
+ * When performing a resync, we need to read and compare, so
+ * we need as many pages are there are copies.
+ * When performing a recovery, we need 2 bios, one for read,
+ * one for write (we recover only one drive per r10buf)
+ *
+ */
+static void * r10buf_pool_alloc(int gfp_flags, void *data)
+{
+	conf_t *conf = data;
+	struct page *page;
+	r10bio_t *r10_bio;
+	struct bio *bio;
+	int i, j;
+	int nalloc;
+
+	r10_bio = r10bio_pool_alloc(gfp_flags, conf);
+	if (!r10_bio) {
+		unplug_slaves(conf->mddev);
+		return NULL;
+	}
+
+	if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
+		nalloc = conf->copies; /* resync */
+	else
+		nalloc = 2; /* recovery */
+
+	/*
+	 * Allocate bios.
+	 */
+	for (j = nalloc ; j-- ; ) {
+		bio = bio_alloc(gfp_flags, RESYNC_PAGES);
+		if (!bio)
+			goto out_free_bio;
+		r10_bio->devs[j].bio = bio;
+	}
+	/*
+	 * Allocate RESYNC_PAGES data pages and attach them
+	 * where needed.
+	 */
+	for (j = 0 ; j < nalloc; j++) {
+		bio = r10_bio->devs[j].bio;
+		for (i = 0; i < RESYNC_PAGES; i++) {
+			page = alloc_page(gfp_flags);
+			if (unlikely(!page))
+				goto out_free_pages;
+
+			bio->bi_io_vec[i].bv_page = page;
+		}
+	}
+
+	return r10_bio;
+
+out_free_pages:
+	for ( ; i > 0 ; i--)
+		__free_page(bio->bi_io_vec[i-1].bv_page);
+	while (j--)
+		for (i = 0; i < RESYNC_PAGES ; i++)
+			__free_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
+	j = -1;
+out_free_bio:
+	while ( ++j < nalloc )
+		bio_put(r10_bio->devs[j].bio);
+	r10bio_pool_free(r10_bio, conf);
+	return NULL;
+}
+
+static void r10buf_pool_free(void *__r10_bio, void *data)
+{
+	int i;
+	conf_t *conf = data;
+	r10bio_t *r10bio = __r10_bio;
+	int j;
+
+	for (j=0; j < conf->copies; j++) {
+		struct bio *bio = r10bio->devs[j].bio;
+		if (bio) {
+			for (i = 0; i < RESYNC_PAGES; i++) {
+				__free_page(bio->bi_io_vec[i].bv_page);
+				bio->bi_io_vec[i].bv_page = NULL;
+			}
+			bio_put(bio);
+		}
+	}
+	r10bio_pool_free(r10bio, conf);
+}
+
+static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
+{
+	int i;
+
+	for (i = 0; i < conf->copies; i++) {
+		struct bio **bio = & r10_bio->devs[i].bio;
+		if (*bio)
+			bio_put(*bio);
+		*bio = NULL;
+	}
+}
+
+static inline void free_r10bio(r10bio_t *r10_bio)
+{
+	unsigned long flags;
+
+	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+
+	/*
+	 * Wake up any possible resync thread that waits for the device
+	 * to go idle.
+	 */
+	spin_lock_irqsave(&conf->resync_lock, flags);
+	if (!--conf->nr_pending) {
+		wake_up(&conf->wait_idle);
+		wake_up(&conf->wait_resume);
+	}
+	spin_unlock_irqrestore(&conf->resync_lock, flags);
+
+	put_all_bios(conf, r10_bio);
+	mempool_free(r10_bio, conf->r10bio_pool);
+}
+
+static inline void put_buf(r10bio_t *r10_bio)
+{
+	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+	unsigned long flags;
+
+	mempool_free(r10_bio, conf->r10buf_pool);
+
+	spin_lock_irqsave(&conf->resync_lock, flags);
+	if (!conf->barrier)
+		BUG();
+	--conf->barrier;
+	wake_up(&conf->wait_resume);
+	wake_up(&conf->wait_idle);
+
+	if (!--conf->nr_pending) {
+		wake_up(&conf->wait_idle);
+		wake_up(&conf->wait_resume);
+	}
+	spin_unlock_irqrestore(&conf->resync_lock, flags);
+}
+
+static void reschedule_retry(r10bio_t *r10_bio)
+{
+	unsigned long flags;
+	mddev_t *mddev = r10_bio->mddev;
+	conf_t *conf = mddev_to_conf(mddev);
+
+	spin_lock_irqsave(&conf->device_lock, flags);
+	list_add(&r10_bio->retry_list, &conf->retry_list);
+	spin_unlock_irqrestore(&conf->device_lock, flags);
+
+	md_wakeup_thread(mddev->thread);
+}
+
+/*
+ * raid_end_bio_io() is called when we have finished servicing a mirrored
+ * operation and are ready to return a success/failure code to the buffer
+ * cache layer.
+ */
+static void raid_end_bio_io(r10bio_t *r10_bio)
+{
+	struct bio *bio = r10_bio->master_bio;
+
+	bio_endio(bio, bio->bi_size,
+		test_bit(R10BIO_Uptodate, &r10_bio->state) ? 0 : -EIO);
+	free_r10bio(r10_bio);
+}
+
+/*
+ * Update disk head position estimator based on IRQ completion info.
+ */
+static inline void update_head_pos(int slot, r10bio_t *r10_bio)
+{
+	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+
+	conf->mirrors[r10_bio->devs[slot].devnum].head_position =
+		r10_bio->devs[slot].addr + (r10_bio->sectors);
+}
+
+static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int error)
+{
+	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+	int slot, dev;
+	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+
+	if (bio->bi_size)
+		return 1;
+
+	slot = r10_bio->read_slot;
+	dev = r10_bio->devs[slot].devnum;
+	/*
+	 * this branch is our 'one mirror IO has finished' event handler:
+	 */
+	if (!uptodate)
+		md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
+	else
+		/*
+		 * Set R10BIO_Uptodate in our master bio, so that
+		 * we will return a good error code to the higher
+		 * levels even if IO on some other mirrored buffer fails.
+		 *
+		 * The 'master' represents the composite IO operation to
+		 * user-side. So if something waits for IO, then it will
+		 * wait for the 'master' bio.
+		 */
+		set_bit(R10BIO_Uptodate, &r10_bio->state);
+
+	update_head_pos(slot, r10_bio);
+
+	/*
+	 * we have only one bio on the read side
+	 */
+	if (uptodate)
+		raid_end_bio_io(r10_bio);
+	else {
+		/*
+		 * oops, read error:
+		 */
+		char b[BDEVNAME_SIZE];
+		if (printk_ratelimit())
+			printk(KERN_ERR "raid10: %s: rescheduling sector %llu\n",
+			       bdevname(conf->mirrors[dev].rdev->bdev,b), (unsigned long long)r10_bio->sector);
+		reschedule_retry(r10_bio);
+	}
+
+	rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+	return 0;
+}
+
+static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, int error)
+{
+	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+	int slot, dev;
+	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+
+	if (bio->bi_size)
+		return 1;
+
+	for (slot = 0; slot < conf->copies; slot++)
+		if (r10_bio->devs[slot].bio == bio)
+			break;
+	dev = r10_bio->devs[slot].devnum;
+
+	/*
+	 * this branch is our 'one mirror IO has finished' event handler:
+	 */
+	if (!uptodate)
+		md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
+	else
+		/*
+		 * Set R10BIO_Uptodate in our master bio, so that
+		 * we will return a good error code for to the higher
+		 * levels even if IO on some other mirrored buffer fails.
+		 *
+		 * The 'master' represents the composite IO operation to
+		 * user-side. So if something waits for IO, then it will
+		 * wait for the 'master' bio.
+		 */
+		set_bit(R10BIO_Uptodate, &r10_bio->state);
+
+	update_head_pos(slot, r10_bio);
+
+	/*
+	 *
+	 * Let's see if all mirrored write operations have finished
+	 * already.
+	 */
+	if (atomic_dec_and_test(&r10_bio->remaining)) {
+		md_write_end(r10_bio->mddev);
+		raid_end_bio_io(r10_bio);
+	}
+
+	rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+	return 0;
+}
+
+
+/*
+ * RAID10 layout manager
+ * Aswell as the chunksize and raid_disks count, there are two
+ * parameters: near_copies and far_copies.
+ * near_copies * far_copies must be <= raid_disks.
+ * Normally one of these will be 1.
+ * If both are 1, we get raid0.
+ * If near_copies == raid_disks, we get raid1.
+ *
+ * Chunks are layed out in raid0 style with near_copies copies of the
+ * first chunk, followed by near_copies copies of the next chunk and
+ * so on.
+ * If far_copies > 1, then after 1/far_copies of the array has been assigned
+ * as described above, we start again with a device offset of near_copies.
+ * So we effectively have another copy of the whole array further down all
+ * the drives, but with blocks on different drives.
+ * With this layout, and block is never stored twice on the one device.
+ *
+ * raid10_find_phys finds the sector offset of a given virtual sector
+ * on each device that it is on. If a block isn't on a device,
+ * that entry in the array is set to MaxSector.
+ *
+ * raid10_find_virt does the reverse mapping, from a device and a
+ * sector offset to a virtual address
+ */
+
+static void raid10_find_phys(conf_t *conf, r10bio_t *r10bio)
+{
+	int n,f;
+	sector_t sector;
+	sector_t chunk;
+	sector_t stripe;
+	int dev;
+
+	int slot = 0;
+
+	/* now calculate first sector/dev */
+	chunk = r10bio->sector >> conf->chunk_shift;
+	sector = r10bio->sector & conf->chunk_mask;
+
+	chunk *= conf->near_copies;
+	stripe = chunk;
+	dev = sector_div(stripe, conf->raid_disks);
+
+	sector += stripe << conf->chunk_shift;
+
+	/* and calculate all the others */
+	for (n=0; n < conf->near_copies; n++) {
+		int d = dev;
+		sector_t s = sector;
+		r10bio->devs[slot].addr = sector;
+		r10bio->devs[slot].devnum = d;
+		slot++;
+
+		for (f = 1; f < conf->far_copies; f++) {
+			d += conf->near_copies;
+			if (d >= conf->raid_disks)
+				d -= conf->raid_disks;
+			s += conf->stride;
+			r10bio->devs[slot].devnum = d;
+			r10bio->devs[slot].addr = s;
+			slot++;
+		}
+		dev++;
+		if (dev >= conf->raid_disks) {
+			dev = 0;
+			sector += (conf->chunk_mask + 1);
+		}
+	}
+	BUG_ON(slot != conf->copies);
+}
+
+static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev)
+{
+	sector_t offset, chunk, vchunk;
+
+	while (sector > conf->stride) {
+		sector -= conf->stride;
+		if (dev < conf->near_copies)
+			dev += conf->raid_disks - conf->near_copies;
+		else
+			dev -= conf->near_copies;
+	}
+
+	offset = sector & conf->chunk_mask;
+	chunk = sector >> conf->chunk_shift;
+	vchunk = chunk * conf->raid_disks + dev;
+	sector_div(vchunk, conf->near_copies);
+	return (vchunk << conf->chunk_shift) + offset;
+}
+
+/**
+ *	raid10_mergeable_bvec -- tell bio layer if a two requests can be merged
+ *	@q: request queue
+ *	@bio: the buffer head that's been built up so far
+ *	@biovec: the request that could be merged to it.
+ *
+ *	Return amount of bytes we can accept at this offset
+ *      If near_copies == raid_disk, there are no striping issues,
+ *      but in that case, the function isn't called at all.
+ */
+static int raid10_mergeable_bvec(request_queue_t *q, struct bio *bio,
+				struct bio_vec *bio_vec)
+{
+	mddev_t *mddev = q->queuedata;
+	sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+	int max;
+	unsigned int chunk_sectors = mddev->chunk_size >> 9;
+	unsigned int bio_sectors = bio->bi_size >> 9;
+
+	max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
+	if (max < 0) max = 0; /* bio_add cannot handle a negative return */
+	if (max <= bio_vec->bv_len && bio_sectors == 0)
+		return bio_vec->bv_len;
+	else
+		return max;
+}
+
+/*
+ * This routine returns the disk from which the requested read should
+ * be done. There is a per-array 'next expected sequential IO' sector
+ * number - if this matches on the next IO then we use the last disk.
+ * There is also a per-disk 'last know head position' sector that is
+ * maintained from IRQ contexts, both the normal and the resync IO
+ * completion handlers update this position correctly. If there is no
+ * perfect sequential match then we pick the disk whose head is closest.
+ *
+ * If there are 2 mirrors in the same 2 devices, performance degrades
+ * because position is mirror, not device based.
+ *
+ * The rdev for the device selected will have nr_pending incremented.
+ */
+
+/*
+ * FIXME: possibly should rethink readbalancing and do it differently
+ * depending on near_copies / far_copies geometry.
+ */
+static int read_balance(conf_t *conf, r10bio_t *r10_bio)
+{
+	const unsigned long this_sector = r10_bio->sector;
+	int disk, slot, nslot;
+	const int sectors = r10_bio->sectors;
+	sector_t new_distance, current_distance;
+
+	raid10_find_phys(conf, r10_bio);
+	spin_lock_irq(&conf->device_lock);
+	/*
+	 * Check if we can balance. We can balance on the whole
+	 * device if no resync is going on, or below the resync window.
+	 * We take the first readable disk when above the resync window.
+	 */
+	if (conf->mddev->recovery_cp < MaxSector
+	    && (this_sector + sectors >= conf->next_resync)) {
+		/* make sure that disk is operational */
+		slot = 0;
+		disk = r10_bio->devs[slot].devnum;
+
+		while (!conf->mirrors[disk].rdev ||
+		       !conf->mirrors[disk].rdev->in_sync) {
+			slot++;
+			if (slot == conf->copies) {
+				slot = 0;
+				disk = -1;
+				break;
+			}
+			disk = r10_bio->devs[slot].devnum;
+		}
+		goto rb_out;
+	}
+
+
+	/* make sure the disk is operational */
+	slot = 0;
+	disk = r10_bio->devs[slot].devnum;
+	while (!conf->mirrors[disk].rdev ||
+	       !conf->mirrors[disk].rdev->in_sync) {
+		slot ++;
+		if (slot == conf->copies) {
+			disk = -1;
+			goto rb_out;
+		}
+		disk = r10_bio->devs[slot].devnum;
+	}
+
+
+	current_distance = abs(this_sector - conf->mirrors[disk].head_position);
+
+	/* Find the disk whose head is closest */
+
+	for (nslot = slot; nslot < conf->copies; nslot++) {
+		int ndisk = r10_bio->devs[nslot].devnum;
+
+
+		if (!conf->mirrors[ndisk].rdev ||
+		    !conf->mirrors[ndisk].rdev->in_sync)
+			continue;
+
+		if (!atomic_read(&conf->mirrors[ndisk].rdev->nr_pending)) {
+			disk = ndisk;
+			slot = nslot;
+			break;
+		}
+		new_distance = abs(r10_bio->devs[nslot].addr -
+				   conf->mirrors[ndisk].head_position);
+		if (new_distance < current_distance) {
+			current_distance = new_distance;
+			disk = ndisk;
+			slot = nslot;
+		}
+	}
+
+rb_out:
+	r10_bio->read_slot = slot;
+/*	conf->next_seq_sect = this_sector + sectors;*/
+
+	if (disk >= 0 && conf->mirrors[disk].rdev)
+		atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
+	spin_unlock_irq(&conf->device_lock);
+
+	return disk;
+}
+
+static void unplug_slaves(mddev_t *mddev)
+{
+	conf_t *conf = mddev_to_conf(mddev);
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&conf->device_lock, flags);
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+		if (rdev && atomic_read(&rdev->nr_pending)) {
+			request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
+
+			atomic_inc(&rdev->nr_pending);
+			spin_unlock_irqrestore(&conf->device_lock, flags);
+
+			if (r_queue->unplug_fn)
+				r_queue->unplug_fn(r_queue);
+
+			spin_lock_irqsave(&conf->device_lock, flags);
+			atomic_dec(&rdev->nr_pending);
+		}
+	}
+	spin_unlock_irqrestore(&conf->device_lock, flags);
+}
+static void raid10_unplug(request_queue_t *q)
+{
+	unplug_slaves(q->queuedata);
+}
+
+static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk,
+			     sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	conf_t *conf = mddev_to_conf(mddev);
+	unsigned long flags;
+	int i, ret = 0;
+
+	spin_lock_irqsave(&conf->device_lock, flags);
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+		if (rdev && !rdev->faulty) {
+			struct block_device *bdev = rdev->bdev;
+			request_queue_t *r_queue = bdev_get_queue(bdev);
+
+			if (r_queue->issue_flush_fn) {
+				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+				if (ret)
+					break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&conf->device_lock, flags);
+	return ret;
+}
+
+/*
+ * Throttle resync depth, so that we can both get proper overlapping of
+ * requests, but are still able to handle normal requests quickly.
+ */
+#define RESYNC_DEPTH 32
+
+static void device_barrier(conf_t *conf, sector_t sect)
+{
+	spin_lock_irq(&conf->resync_lock);
+	wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
+			    conf->resync_lock, unplug_slaves(conf->mddev));
+
+	if (!conf->barrier++) {
+		wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
+				    conf->resync_lock, unplug_slaves(conf->mddev));
+		if (conf->nr_pending)
+			BUG();
+	}
+	wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
+			    conf->resync_lock, unplug_slaves(conf->mddev));
+	conf->next_resync = sect;
+	spin_unlock_irq(&conf->resync_lock);
+}
+
+static int make_request(request_queue_t *q, struct bio * bio)
+{
+	mddev_t *mddev = q->queuedata;
+	conf_t *conf = mddev_to_conf(mddev);
+	mirror_info_t *mirror;
+	r10bio_t *r10_bio;
+	struct bio *read_bio;
+	int i;
+	int chunk_sects = conf->chunk_mask + 1;
+
+	/* If this request crosses a chunk boundary, we need to
+	 * split it.  This will only happen for 1 PAGE (or less) requests.
+	 */
+	if (unlikely( (bio->bi_sector & conf->chunk_mask) + (bio->bi_size >> 9)
+		      > chunk_sects &&
+		    conf->near_copies < conf->raid_disks)) {
+		struct bio_pair *bp;
+		/* Sanity check -- queue functions should prevent this happening */
+		if (bio->bi_vcnt != 1 ||
+		    bio->bi_idx != 0)
+			goto bad_map;
+		/* This is a one page bio that upper layers
+		 * refuse to split for us, so we need to split it.
+		 */
+		bp = bio_split(bio, bio_split_pool,
+			       chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
+		if (make_request(q, &bp->bio1))
+			generic_make_request(&bp->bio1);
+		if (make_request(q, &bp->bio2))
+			generic_make_request(&bp->bio2);
+
+		bio_pair_release(bp);
+		return 0;
+	bad_map:
+		printk("raid10_make_request bug: can't convert block across chunks"
+		       " or bigger than %dk %llu %d\n", chunk_sects/2,
+		       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
+
+		bio_io_error(bio, bio->bi_size);
+		return 0;
+	}
+
+	/*
+	 * Register the new request and wait if the reconstruction
+	 * thread has put up a bar for new requests.
+	 * Continue immediately if no resync is active currently.
+	 */
+	spin_lock_irq(&conf->resync_lock);
+	wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
+	conf->nr_pending++;
+	spin_unlock_irq(&conf->resync_lock);
+
+	if (bio_data_dir(bio)==WRITE) {
+		disk_stat_inc(mddev->gendisk, writes);
+		disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
+	} else {
+		disk_stat_inc(mddev->gendisk, reads);
+		disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
+	}
+
+	r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
+
+	r10_bio->master_bio = bio;
+	r10_bio->sectors = bio->bi_size >> 9;
+
+	r10_bio->mddev = mddev;
+	r10_bio->sector = bio->bi_sector;
+
+	if (bio_data_dir(bio) == READ) {
+		/*
+		 * read balancing logic:
+		 */
+		int disk = read_balance(conf, r10_bio);
+		int slot = r10_bio->read_slot;
+		if (disk < 0) {
+			raid_end_bio_io(r10_bio);
+			return 0;
+		}
+		mirror = conf->mirrors + disk;
+
+		read_bio = bio_clone(bio, GFP_NOIO);
+
+		r10_bio->devs[slot].bio = read_bio;
+
+		read_bio->bi_sector = r10_bio->devs[slot].addr +
+			mirror->rdev->data_offset;
+		read_bio->bi_bdev = mirror->rdev->bdev;
+		read_bio->bi_end_io = raid10_end_read_request;
+		read_bio->bi_rw = READ;
+		read_bio->bi_private = r10_bio;
+
+		generic_make_request(read_bio);
+		return 0;
+	}
+
+	/*
+	 * WRITE:
+	 */
+	/* first select target devices under spinlock and
+	 * inc refcount on their rdev.  Record them by setting
+	 * bios[x] to bio
+	 */
+	raid10_find_phys(conf, r10_bio);
+	spin_lock_irq(&conf->device_lock);
+	for (i = 0;  i < conf->copies; i++) {
+		int d = r10_bio->devs[i].devnum;
+		if (conf->mirrors[d].rdev &&
+		    !conf->mirrors[d].rdev->faulty) {
+			atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+			r10_bio->devs[i].bio = bio;
+		} else
+			r10_bio->devs[i].bio = NULL;
+	}
+	spin_unlock_irq(&conf->device_lock);
+
+	atomic_set(&r10_bio->remaining, 1);
+	md_write_start(mddev);
+	for (i = 0; i < conf->copies; i++) {
+		struct bio *mbio;
+		int d = r10_bio->devs[i].devnum;
+		if (!r10_bio->devs[i].bio)
+			continue;
+
+		mbio = bio_clone(bio, GFP_NOIO);
+		r10_bio->devs[i].bio = mbio;
+
+		mbio->bi_sector	= r10_bio->devs[i].addr+
+			conf->mirrors[d].rdev->data_offset;
+		mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
+		mbio->bi_end_io	= raid10_end_write_request;
+		mbio->bi_rw = WRITE;
+		mbio->bi_private = r10_bio;
+
+		atomic_inc(&r10_bio->remaining);
+		generic_make_request(mbio);
+	}
+
+	if (atomic_dec_and_test(&r10_bio->remaining)) {
+		md_write_end(mddev);
+		raid_end_bio_io(r10_bio);
+	}
+
+	return 0;
+}
+
+static void status(struct seq_file *seq, mddev_t *mddev)
+{
+	conf_t *conf = mddev_to_conf(mddev);
+	int i;
+
+	if (conf->near_copies < conf->raid_disks)
+		seq_printf(seq, " %dK chunks", mddev->chunk_size/1024);
+	if (conf->near_copies > 1)
+		seq_printf(seq, " %d near-copies", conf->near_copies);
+	if (conf->far_copies > 1)
+		seq_printf(seq, " %d far-copies", conf->far_copies);
+
+	seq_printf(seq, " [%d/%d] [", conf->raid_disks,
+						conf->working_disks);
+	for (i = 0; i < conf->raid_disks; i++)
+		seq_printf(seq, "%s",
+			      conf->mirrors[i].rdev &&
+			      conf->mirrors[i].rdev->in_sync ? "U" : "_");
+	seq_printf(seq, "]");
+}
+
+static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+	char b[BDEVNAME_SIZE];
+	conf_t *conf = mddev_to_conf(mddev);
+
+	/*
+	 * If it is not operational, then we have already marked it as dead
+	 * else if it is the last working disks, ignore the error, let the
+	 * next level up know.
+	 * else mark the drive as failed
+	 */
+	if (rdev->in_sync
+	    && conf->working_disks == 1)
+		/*
+		 * Don't fail the drive, just return an IO error.
+		 * The test should really be more sophisticated than
+		 * "working_disks == 1", but it isn't critical, and
+		 * can wait until we do more sophisticated "is the drive
+		 * really dead" tests...
+		 */
+		return;
+	if (rdev->in_sync) {
+		mddev->degraded++;
+		conf->working_disks--;
+		/*
+		 * if recovery is running, make sure it aborts.
+		 */
+		set_bit(MD_RECOVERY_ERR, &mddev->recovery);
+	}
+	rdev->in_sync = 0;
+	rdev->faulty = 1;
+	mddev->sb_dirty = 1;
+	printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n"
+		"	Operation continuing on %d devices\n",
+		bdevname(rdev->bdev,b), conf->working_disks);
+}
+
+static void print_conf(conf_t *conf)
+{
+	int i;
+	mirror_info_t *tmp;
+
+	printk("RAID10 conf printout:\n");
+	if (!conf) {
+		printk("(!conf)\n");
+		return;
+	}
+	printk(" --- wd:%d rd:%d\n", conf->working_disks,
+		conf->raid_disks);
+
+	for (i = 0; i < conf->raid_disks; i++) {
+		char b[BDEVNAME_SIZE];
+		tmp = conf->mirrors + i;
+		if (tmp->rdev)
+			printk(" disk %d, wo:%d, o:%d, dev:%s\n",
+				i, !tmp->rdev->in_sync, !tmp->rdev->faulty,
+				bdevname(tmp->rdev->bdev,b));
+	}
+}
+
+static void close_sync(conf_t *conf)
+{
+	spin_lock_irq(&conf->resync_lock);
+	wait_event_lock_irq(conf->wait_resume, !conf->barrier,
+			    conf->resync_lock, 	unplug_slaves(conf->mddev));
+	spin_unlock_irq(&conf->resync_lock);
+
+	if (conf->barrier) BUG();
+	if (waitqueue_active(&conf->wait_idle)) BUG();
+
+	mempool_destroy(conf->r10buf_pool);
+	conf->r10buf_pool = NULL;
+}
+
+static int raid10_spare_active(mddev_t *mddev)
+{
+	int i;
+	conf_t *conf = mddev->private;
+	mirror_info_t *tmp;
+
+	spin_lock_irq(&conf->device_lock);
+	/*
+	 * Find all non-in_sync disks within the RAID10 configuration
+	 * and mark them in_sync
+	 */
+	for (i = 0; i < conf->raid_disks; i++) {
+		tmp = conf->mirrors + i;
+		if (tmp->rdev
+		    && !tmp->rdev->faulty
+		    && !tmp->rdev->in_sync) {
+			conf->working_disks++;
+			mddev->degraded--;
+			tmp->rdev->in_sync = 1;
+		}
+	}
+	spin_unlock_irq(&conf->device_lock);
+
+	print_conf(conf);
+	return 0;
+}
+
+
+static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+	conf_t *conf = mddev->private;
+	int found = 0;
+	int mirror;
+	mirror_info_t *p;
+
+	if (mddev->recovery_cp < MaxSector)
+		/* only hot-add to in-sync arrays, as recovery is
+		 * very different from resync
+		 */
+		return 0;
+	spin_lock_irq(&conf->device_lock);
+	for (mirror=0; mirror < mddev->raid_disks; mirror++)
+		if ( !(p=conf->mirrors+mirror)->rdev) {
+			p->rdev = rdev;
+
+			blk_queue_stack_limits(mddev->queue,
+					       rdev->bdev->bd_disk->queue);
+			/* as we don't honour merge_bvec_fn, we must never risk
+			 * violating it, so limit ->max_sector to one PAGE, as
+			 * a one page request is never in violation.
+			 */
+			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+				mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
+			p->head_position = 0;
+			rdev->raid_disk = mirror;
+			found = 1;
+			break;
+		}
+	spin_unlock_irq(&conf->device_lock);
+
+	print_conf(conf);
+	return found;
+}
+
+static int raid10_remove_disk(mddev_t *mddev, int number)
+{
+	conf_t *conf = mddev->private;
+	int err = 1;
+	mirror_info_t *p = conf->mirrors+ number;
+
+	print_conf(conf);
+	spin_lock_irq(&conf->device_lock);
+	if (p->rdev) {
+		if (p->rdev->in_sync ||
+		    atomic_read(&p->rdev->nr_pending)) {
+			err = -EBUSY;
+			goto abort;
+		}
+		p->rdev = NULL;
+		err = 0;
+	}
+	if (err)
+		MD_BUG();
+abort:
+	spin_unlock_irq(&conf->device_lock);
+
+	print_conf(conf);
+	return err;
+}
+
+
+static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
+{
+	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+	int i,d;
+
+	if (bio->bi_size)
+		return 1;
+
+	for (i=0; i<conf->copies; i++)
+		if (r10_bio->devs[i].bio == bio)
+			break;
+	if (i == conf->copies)
+		BUG();
+	update_head_pos(i, r10_bio);
+	d = r10_bio->devs[i].devnum;
+	if (!uptodate)
+		md_error(r10_bio->mddev,
+			 conf->mirrors[d].rdev);
+
+	/* for reconstruct, we always reschedule after a read.
+	 * for resync, only after all reads
+	 */
+	if (test_bit(R10BIO_IsRecover, &r10_bio->state) ||
+	    atomic_dec_and_test(&r10_bio->remaining)) {
+		/* we have read all the blocks,
+		 * do the comparison in process context in raid10d
+		 */
+		reschedule_retry(r10_bio);
+	}
+	rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
+	return 0;
+}
+
+static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
+{
+	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+	mddev_t *mddev = r10_bio->mddev;
+	conf_t *conf = mddev_to_conf(mddev);
+	int i,d;
+
+	if (bio->bi_size)
+		return 1;
+
+	for (i = 0; i < conf->copies; i++)
+		if (r10_bio->devs[i].bio == bio)
+			break;
+	d = r10_bio->devs[i].devnum;
+
+	if (!uptodate)
+		md_error(mddev, conf->mirrors[d].rdev);
+	update_head_pos(i, r10_bio);
+
+	while (atomic_dec_and_test(&r10_bio->remaining)) {
+		if (r10_bio->master_bio == NULL) {
+			/* the primary of several recovery bios */
+			md_done_sync(mddev, r10_bio->sectors, 1);
+			put_buf(r10_bio);
+			break;
+		} else {
+			r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
+			put_buf(r10_bio);
+			r10_bio = r10_bio2;
+		}
+	}
+	rdev_dec_pending(conf->mirrors[d].rdev, mddev);
+	return 0;
+}
+
+/*
+ * Note: sync and recover and handled very differently for raid10
+ * This code is for resync.
+ * For resync, we read through virtual addresses and read all blocks.
+ * If there is any error, we schedule a write.  The lowest numbered
+ * drive is authoritative.
+ * However requests come for physical address, so we need to map.
+ * For every physical address there are raid_disks/copies virtual addresses,
+ * which is always are least one, but is not necessarly an integer.
+ * This means that a physical address can span multiple chunks, so we may
+ * have to submit multiple io requests for a single sync request.
+ */
+/*
+ * We check if all blocks are in-sync and only write to blocks that
+ * aren't in sync
+ */
+static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+{
+	conf_t *conf = mddev_to_conf(mddev);
+	int i, first;
+	struct bio *tbio, *fbio;
+
+	atomic_set(&r10_bio->remaining, 1);
+
+	/* find the first device with a block */
+	for (i=0; i<conf->copies; i++)
+		if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags))
+			break;
+
+	if (i == conf->copies)
+		goto done;
+
+	first = i;
+	fbio = r10_bio->devs[i].bio;
+
+	/* now find blocks with errors */
+	for (i=first+1 ; i < conf->copies ; i++) {
+		int vcnt, j, d;
+
+		if (!test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags))
+			continue;
+		/* We know that the bi_io_vec layout is the same for
+		 * both 'first' and 'i', so we just compare them.
+		 * All vec entries are PAGE_SIZE;
+		 */
+		tbio = r10_bio->devs[i].bio;
+		vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
+		for (j = 0; j < vcnt; j++)
+			if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
+				   page_address(tbio->bi_io_vec[j].bv_page),
+				   PAGE_SIZE))
+				break;
+		if (j == vcnt)
+			continue;
+		/* Ok, we need to write this bio
+		 * First we need to fixup bv_offset, bv_len and
+		 * bi_vecs, as the read request might have corrupted these
+		 */
+		tbio->bi_vcnt = vcnt;
+		tbio->bi_size = r10_bio->sectors << 9;
+		tbio->bi_idx = 0;
+		tbio->bi_phys_segments = 0;
+		tbio->bi_hw_segments = 0;
+		tbio->bi_hw_front_size = 0;
+		tbio->bi_hw_back_size = 0;
+		tbio->bi_flags &= ~(BIO_POOL_MASK - 1);
+		tbio->bi_flags |= 1 << BIO_UPTODATE;
+		tbio->bi_next = NULL;
+		tbio->bi_rw = WRITE;
+		tbio->bi_private = r10_bio;
+		tbio->bi_sector = r10_bio->devs[i].addr;
+
+		for (j=0; j < vcnt ; j++) {
+			tbio->bi_io_vec[j].bv_offset = 0;
+			tbio->bi_io_vec[j].bv_len = PAGE_SIZE;
+
+			memcpy(page_address(tbio->bi_io_vec[j].bv_page),
+			       page_address(fbio->bi_io_vec[j].bv_page),
+			       PAGE_SIZE);
+		}
+		tbio->bi_end_io = end_sync_write;
+
+		d = r10_bio->devs[i].devnum;
+		atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+		atomic_inc(&r10_bio->remaining);
+		md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9);
+
+		generic_make_request(tbio);
+	}
+
+done:
+	if (atomic_dec_and_test(&r10_bio->remaining)) {
+		md_done_sync(mddev, r10_bio->sectors, 1);
+		put_buf(r10_bio);
+	}
+}
+
+/*
+ * Now for the recovery code.
+ * Recovery happens across physical sectors.
+ * We recover all non-is_sync drives by finding the virtual address of
+ * each, and then choose a working drive that also has that virt address.
+ * There is a separate r10_bio for each non-in_sync drive.
+ * Only the first two slots are in use. The first for reading,
+ * The second for writing.
+ *
+ */
+
+static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+{
+	conf_t *conf = mddev_to_conf(mddev);
+	int i, d;
+	struct bio *bio, *wbio;
+
+
+	/* move the pages across to the second bio
+	 * and submit the write request
+	 */
+	bio = r10_bio->devs[0].bio;
+	wbio = r10_bio->devs[1].bio;
+	for (i=0; i < wbio->bi_vcnt; i++) {
+		struct page *p = bio->bi_io_vec[i].bv_page;
+		bio->bi_io_vec[i].bv_page = wbio->bi_io_vec[i].bv_page;
+		wbio->bi_io_vec[i].bv_page = p;
+	}
+	d = r10_bio->devs[1].devnum;
+
+	atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+	md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
+	generic_make_request(wbio);
+}
+
+
+/*
+ * This is a kernel thread which:
+ *
+ *	1.	Retries failed read operations on working mirrors.
+ *	2.	Updates the raid superblock when problems encounter.
+ *	3.	Performs writes following reads for array syncronising.
+ */
+
+static void raid10d(mddev_t *mddev)
+{
+	r10bio_t *r10_bio;
+	struct bio *bio;
+	unsigned long flags;
+	conf_t *conf = mddev_to_conf(mddev);
+	struct list_head *head = &conf->retry_list;
+	int unplug=0;
+	mdk_rdev_t *rdev;
+
+	md_check_recovery(mddev);
+	md_handle_safemode(mddev);
+
+	for (;;) {
+		char b[BDEVNAME_SIZE];
+		spin_lock_irqsave(&conf->device_lock, flags);
+		if (list_empty(head))
+			break;
+		r10_bio = list_entry(head->prev, r10bio_t, retry_list);
+		list_del(head->prev);
+		spin_unlock_irqrestore(&conf->device_lock, flags);
+
+		mddev = r10_bio->mddev;
+		conf = mddev_to_conf(mddev);
+		if (test_bit(R10BIO_IsSync, &r10_bio->state)) {
+			sync_request_write(mddev, r10_bio);
+			unplug = 1;
+		} else 	if (test_bit(R10BIO_IsRecover, &r10_bio->state)) {
+			recovery_request_write(mddev, r10_bio);
+			unplug = 1;
+		} else {
+			int mirror;
+			bio = r10_bio->devs[r10_bio->read_slot].bio;
+			r10_bio->devs[r10_bio->read_slot].bio = NULL;
+			mirror = read_balance(conf, r10_bio);
+			r10_bio->devs[r10_bio->read_slot].bio = bio;
+			if (mirror == -1) {
+				printk(KERN_ALERT "raid10: %s: unrecoverable I/O"
+				       " read error for block %llu\n",
+				       bdevname(bio->bi_bdev,b),
+				       (unsigned long long)r10_bio->sector);
+				raid_end_bio_io(r10_bio);
+			} else {
+				rdev = conf->mirrors[mirror].rdev;
+				if (printk_ratelimit())
+					printk(KERN_ERR "raid10: %s: redirecting sector %llu to"
+					       " another mirror\n",
+					       bdevname(rdev->bdev,b),
+					       (unsigned long long)r10_bio->sector);
+				bio->bi_bdev = rdev->bdev;
+				bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr
+					+ rdev->data_offset;
+				bio->bi_next = NULL;
+				bio->bi_flags &= (1<<BIO_CLONED);
+				bio->bi_flags |= 1 << BIO_UPTODATE;
+				bio->bi_idx = 0;
+				bio->bi_size = r10_bio->sectors << 9;
+				bio->bi_rw = READ;
+				unplug = 1;
+				generic_make_request(bio);
+			}
+		}
+	}
+	spin_unlock_irqrestore(&conf->device_lock, flags);
+	if (unplug)
+		unplug_slaves(mddev);
+}
+
+
+static int init_resync(conf_t *conf)
+{
+	int buffs;
+
+	buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
+	if (conf->r10buf_pool)
+		BUG();
+	conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf);
+	if (!conf->r10buf_pool)
+		return -ENOMEM;
+	conf->next_resync = 0;
+	return 0;
+}
+
+/*
+ * perform a "sync" on one "block"
+ *
+ * We need to make sure that no normal I/O request - particularly write
+ * requests - conflict with active sync requests.
+ *
+ * This is achieved by tracking pending requests and a 'barrier' concept
+ * that can be installed to exclude normal IO requests.
+ *
+ * Resync and recovery are handled very differently.
+ * We differentiate by looking at MD_RECOVERY_SYNC in mddev->recovery.
+ *
+ * For resync, we iterate over virtual addresses, read all copies,
+ * and update if there are differences.  If only one copy is live,
+ * skip it.
+ * For recovery, we iterate over physical addresses, read a good
+ * value for each non-in_sync drive, and over-write.
+ *
+ * So, for recovery we may have several outstanding complex requests for a
+ * given address, one for each out-of-sync device.  We model this by allocating
+ * a number of r10_bio structures, one for each out-of-sync device.
+ * As we setup these structures, we collect all bio's together into a list
+ * which we then process collectively to add pages, and then process again
+ * to pass to generic_make_request.
+ *
+ * The r10_bio structures are linked using a borrowed master_bio pointer.
+ * This link is counted in ->remaining.  When the r10_bio that points to NULL
+ * has its remaining count decremented to 0, the whole complex operation
+ * is complete.
+ *
+ */
+
+static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+{
+	conf_t *conf = mddev_to_conf(mddev);
+	r10bio_t *r10_bio;
+	struct bio *biolist = NULL, *bio;
+	sector_t max_sector, nr_sectors;
+	int disk;
+	int i;
+
+	sector_t sectors_skipped = 0;
+	int chunks_skipped = 0;
+
+	if (!conf->r10buf_pool)
+		if (init_resync(conf))
+			return -ENOMEM;
+
+ skipped:
+	max_sector = mddev->size << 1;
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+		max_sector = mddev->resync_max_sectors;
+	if (sector_nr >= max_sector) {
+		close_sync(conf);
+		return sectors_skipped;
+	}
+	if (chunks_skipped >= conf->raid_disks) {
+		/* if there has been nothing to do on any drive,
+		 * then there is nothing to do at all..
+		 */
+		sector_t sec = max_sector - sector_nr;
+		md_done_sync(mddev, sec, 1);
+		return sec + sectors_skipped;
+	}
+
+	/* make sure whole request will fit in a chunk - if chunks
+	 * are meaningful
+	 */
+	if (conf->near_copies < conf->raid_disks &&
+	    max_sector > (sector_nr | conf->chunk_mask))
+		max_sector = (sector_nr | conf->chunk_mask) + 1;
+	/*
+	 * If there is non-resync activity waiting for us then
+	 * put in a delay to throttle resync.
+	 */
+	if (!go_faster && waitqueue_active(&conf->wait_resume))
+		schedule_timeout(HZ);
+	device_barrier(conf, sector_nr + RESYNC_SECTORS);
+
+	/* Again, very different code for resync and recovery.
+	 * Both must result in an r10bio with a list of bios that
+	 * have bi_end_io, bi_sector, bi_bdev set,
+	 * and bi_private set to the r10bio.
+	 * For recovery, we may actually create several r10bios
+	 * with 2 bios in each, that correspond to the bios in the main one.
+	 * In this case, the subordinate r10bios link back through a
+	 * borrowed master_bio pointer, and the counter in the master
+	 * includes a ref from each subordinate.
+	 */
+	/* First, we decide what to do and set ->bi_end_io
+	 * To end_sync_read if we want to read, and
+	 * end_sync_write if we will want to write.
+	 */
+
+	if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+		/* recovery... the complicated one */
+		int i, j, k;
+		r10_bio = NULL;
+
+		for (i=0 ; i<conf->raid_disks; i++)
+			if (conf->mirrors[i].rdev &&
+			    !conf->mirrors[i].rdev->in_sync) {
+				/* want to reconstruct this device */
+				r10bio_t *rb2 = r10_bio;
+
+				r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+				spin_lock_irq(&conf->resync_lock);
+				conf->nr_pending++;
+				if (rb2) conf->barrier++;
+				spin_unlock_irq(&conf->resync_lock);
+				atomic_set(&r10_bio->remaining, 0);
+
+				r10_bio->master_bio = (struct bio*)rb2;
+				if (rb2)
+					atomic_inc(&rb2->remaining);
+				r10_bio->mddev = mddev;
+				set_bit(R10BIO_IsRecover, &r10_bio->state);
+				r10_bio->sector = raid10_find_virt(conf, sector_nr, i);
+				raid10_find_phys(conf, r10_bio);
+				for (j=0; j<conf->copies;j++) {
+					int d = r10_bio->devs[j].devnum;
+					if (conf->mirrors[d].rdev &&
+					    conf->mirrors[d].rdev->in_sync) {
+						/* This is where we read from */
+						bio = r10_bio->devs[0].bio;
+						bio->bi_next = biolist;
+						biolist = bio;
+						bio->bi_private = r10_bio;
+						bio->bi_end_io = end_sync_read;
+						bio->bi_rw = 0;
+						bio->bi_sector = r10_bio->devs[j].addr +
+							conf->mirrors[d].rdev->data_offset;
+						bio->bi_bdev = conf->mirrors[d].rdev->bdev;
+						atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+						atomic_inc(&r10_bio->remaining);
+						/* and we write to 'i' */
+
+						for (k=0; k<conf->copies; k++)
+							if (r10_bio->devs[k].devnum == i)
+								break;
+						bio = r10_bio->devs[1].bio;
+						bio->bi_next = biolist;
+						biolist = bio;
+						bio->bi_private = r10_bio;
+						bio->bi_end_io = end_sync_write;
+						bio->bi_rw = 1;
+						bio->bi_sector = r10_bio->devs[k].addr +
+							conf->mirrors[i].rdev->data_offset;
+						bio->bi_bdev = conf->mirrors[i].rdev->bdev;
+
+						r10_bio->devs[0].devnum = d;
+						r10_bio->devs[1].devnum = i;
+
+						break;
+					}
+				}
+				if (j == conf->copies) {
+					BUG();
+				}
+			}
+		if (biolist == NULL) {
+			while (r10_bio) {
+				r10bio_t *rb2 = r10_bio;
+				r10_bio = (r10bio_t*) rb2->master_bio;
+				rb2->master_bio = NULL;
+				put_buf(rb2);
+			}
+			goto giveup;
+		}
+	} else {
+		/* resync. Schedule a read for every block at this virt offset */
+		int count = 0;
+		r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
+
+		spin_lock_irq(&conf->resync_lock);
+		conf->nr_pending++;
+		spin_unlock_irq(&conf->resync_lock);
+
+		r10_bio->mddev = mddev;
+		atomic_set(&r10_bio->remaining, 0);
+
+		r10_bio->master_bio = NULL;
+		r10_bio->sector = sector_nr;
+		set_bit(R10BIO_IsSync, &r10_bio->state);
+		raid10_find_phys(conf, r10_bio);
+		r10_bio->sectors = (sector_nr | conf->chunk_mask) - sector_nr +1;
+		spin_lock_irq(&conf->device_lock);
+		for (i=0; i<conf->copies; i++) {
+			int d = r10_bio->devs[i].devnum;
+			bio = r10_bio->devs[i].bio;
+			bio->bi_end_io = NULL;
+			if (conf->mirrors[d].rdev == NULL ||
+			    conf->mirrors[d].rdev->faulty)
+				continue;
+			atomic_inc(&conf->mirrors[d].rdev->nr_pending);
+			atomic_inc(&r10_bio->remaining);
+			bio->bi_next = biolist;
+			biolist = bio;
+			bio->bi_private = r10_bio;
+			bio->bi_end_io = end_sync_read;
+			bio->bi_rw = 0;
+			bio->bi_sector = r10_bio->devs[i].addr +
+				conf->mirrors[d].rdev->data_offset;
+			bio->bi_bdev = conf->mirrors[d].rdev->bdev;
+			count++;
+		}
+		spin_unlock_irq(&conf->device_lock);
+		if (count < 2) {
+			for (i=0; i<conf->copies; i++) {
+				int d = r10_bio->devs[i].devnum;
+				if (r10_bio->devs[i].bio->bi_end_io)
+					atomic_dec(&conf->mirrors[d].rdev->nr_pending);
+			}
+			put_buf(r10_bio);
+			goto giveup;
+		}
+	}
+
+	for (bio = biolist; bio ; bio=bio->bi_next) {
+
+		bio->bi_flags &= ~(BIO_POOL_MASK - 1);
+		if (bio->bi_end_io)
+			bio->bi_flags |= 1 << BIO_UPTODATE;
+		bio->bi_vcnt = 0;
+		bio->bi_idx = 0;
+		bio->bi_phys_segments = 0;
+		bio->bi_hw_segments = 0;
+		bio->bi_size = 0;
+	}
+
+	nr_sectors = 0;
+	do {
+		struct page *page;
+		int len = PAGE_SIZE;
+		disk = 0;
+		if (sector_nr + (len>>9) > max_sector)
+			len = (max_sector - sector_nr) << 9;
+		if (len == 0)
+			break;
+		for (bio= biolist ; bio ; bio=bio->bi_next) {
+			page = bio->bi_io_vec[bio->bi_vcnt].bv_page;
+			if (bio_add_page(bio, page, len, 0) == 0) {
+				/* stop here */
+				struct bio *bio2;
+				bio->bi_io_vec[bio->bi_vcnt].bv_page = page;
+				for (bio2 = biolist; bio2 && bio2 != bio; bio2 = bio2->bi_next) {
+					/* remove last page from this bio */
+					bio2->bi_vcnt--;
+					bio2->bi_size -= len;
+					bio2->bi_flags &= ~(1<< BIO_SEG_VALID);
+				}
+				goto bio_full;
+			}
+			disk = i;
+		}
+		nr_sectors += len>>9;
+		sector_nr += len>>9;
+	} while (biolist->bi_vcnt < RESYNC_PAGES);
+ bio_full:
+	r10_bio->sectors = nr_sectors;
+
+	while (biolist) {
+		bio = biolist;
+		biolist = biolist->bi_next;
+
+		bio->bi_next = NULL;
+		r10_bio = bio->bi_private;
+		r10_bio->sectors = nr_sectors;
+
+		if (bio->bi_end_io == end_sync_read) {
+			md_sync_acct(bio->bi_bdev, nr_sectors);
+			generic_make_request(bio);
+		}
+	}
+
+	return nr_sectors;
+ giveup:
+	/* There is nowhere to write, so all non-sync
+	 * drives must be failed, so try the next chunk...
+	 */
+	{
+	int sec = max_sector - sector_nr;
+	sectors_skipped += sec;
+	chunks_skipped ++;
+	sector_nr = max_sector;
+	md_done_sync(mddev, sec, 1);
+	goto skipped;
+	}
+}
+
+static int run(mddev_t *mddev)
+{
+	conf_t *conf;
+	int i, disk_idx;
+	mirror_info_t *disk;
+	mdk_rdev_t *rdev;
+	struct list_head *tmp;
+	int nc, fc;
+	sector_t stride, size;
+
+	if (mddev->level != 10) {
+		printk(KERN_ERR "raid10: %s: raid level not set correctly... (%d)\n",
+		       mdname(mddev), mddev->level);
+		goto out;
+	}
+	nc = mddev->layout & 255;
+	fc = (mddev->layout >> 8) & 255;
+	if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
+	    (mddev->layout >> 16)) {
+		printk(KERN_ERR "raid10: %s: unsupported raid10 layout: 0x%8x\n",
+		       mdname(mddev), mddev->layout);
+		goto out;
+	}
+	/*
+	 * copy the already verified devices into our private RAID10
+	 * bookkeeping area. [whatever we allocate in run(),
+	 * should be freed in stop()]
+	 */
+	conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
+	mddev->private = conf;
+	if (!conf) {
+		printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
+			mdname(mddev));
+		goto out;
+	}
+	memset(conf, 0, sizeof(*conf));
+	conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks,
+				 GFP_KERNEL);
+	if (!conf->mirrors) {
+		printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
+		       mdname(mddev));
+		goto out_free_conf;
+	}
+	memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
+
+	conf->near_copies = nc;
+	conf->far_copies = fc;
+	conf->copies = nc*fc;
+	conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1;
+	conf->chunk_shift = ffz(~mddev->chunk_size) - 9;
+	stride = mddev->size >> (conf->chunk_shift-1);
+	sector_div(stride, fc);
+	conf->stride = stride << conf->chunk_shift;
+
+	conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
+						r10bio_pool_free, conf);
+	if (!conf->r10bio_pool) {
+		printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
+			mdname(mddev));
+		goto out_free_conf;
+	}
+	mddev->queue->unplug_fn = raid10_unplug;
+
+	mddev->queue->issue_flush_fn = raid10_issue_flush;
+
+	ITERATE_RDEV(mddev, rdev, tmp) {
+		disk_idx = rdev->raid_disk;
+		if (disk_idx >= mddev->raid_disks
+		    || disk_idx < 0)
+			continue;
+		disk = conf->mirrors + disk_idx;
+
+		disk->rdev = rdev;
+
+		blk_queue_stack_limits(mddev->queue,
+				       rdev->bdev->bd_disk->queue);
+		/* as we don't honour merge_bvec_fn, we must never risk
+		 * violating it, so limit ->max_sector to one PAGE, as
+		 * a one page request is never in violation.
+		 */
+		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
+		disk->head_position = 0;
+		if (!rdev->faulty && rdev->in_sync)
+			conf->working_disks++;
+	}
+	conf->raid_disks = mddev->raid_disks;
+	conf->mddev = mddev;
+	conf->device_lock = SPIN_LOCK_UNLOCKED;
+	INIT_LIST_HEAD(&conf->retry_list);
+
+	conf->resync_lock = SPIN_LOCK_UNLOCKED;
+	init_waitqueue_head(&conf->wait_idle);
+	init_waitqueue_head(&conf->wait_resume);
+
+	if (!conf->working_disks) {
+		printk(KERN_ERR "raid10: no operational mirrors for %s\n",
+			mdname(mddev));
+		goto out_free_conf;
+	}
+
+	mddev->degraded = 0;
+	for (i = 0; i < conf->raid_disks; i++) {
+
+		disk = conf->mirrors + i;
+
+		if (!disk->rdev) {
+			disk->head_position = 0;
+			mddev->degraded++;
+		}
+	}
+
+
+	mddev->thread = md_register_thread(raid10d, mddev, "%s_raid10");
+	if (!mddev->thread) {
+		printk(KERN_ERR
+		       "raid10: couldn't allocate thread for %s\n",
+		       mdname(mddev));
+		goto out_free_conf;
+	}
+
+	printk(KERN_INFO
+		"raid10: raid set %s active with %d out of %d devices\n",
+		mdname(mddev), mddev->raid_disks - mddev->degraded,
+		mddev->raid_disks);
+	/*
+	 * Ok, everything is just fine now
+	 */
+	size = conf->stride * conf->raid_disks;
+	sector_div(size, conf->near_copies);
+	mddev->array_size = size/2;
+	mddev->resync_max_sectors = size;
+
+	/* Calculate max read-ahead size.
+	 * We need to readahead at least twice a whole stripe....
+	 * maybe...
+	 */
+	{
+		int stripe = conf->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+		stripe /= conf->near_copies;
+		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
+			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
+	}
+
+	if (conf->near_copies < mddev->raid_disks)
+		blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
+	return 0;
+
+out_free_conf:
+	if (conf->r10bio_pool)
+		mempool_destroy(conf->r10bio_pool);
+	if (conf->mirrors)
+		kfree(conf->mirrors);
+	kfree(conf);
+	mddev->private = NULL;
+out:
+	return -EIO;
+}
+
+static int stop(mddev_t *mddev)
+{
+	conf_t *conf = mddev_to_conf(mddev);
+
+	md_unregister_thread(mddev->thread);
+	mddev->thread = NULL;
+	if (conf->r10bio_pool)
+		mempool_destroy(conf->r10bio_pool);
+	if (conf->mirrors)
+		kfree(conf->mirrors);
+	kfree(conf);
+	mddev->private = NULL;
+	return 0;
+}
+
+
+static mdk_personality_t raid10_personality =
+{
+	.name		= "raid10",
+	.owner		= THIS_MODULE,
+	.make_request	= make_request,
+	.run		= run,
+	.stop		= stop,
+	.status		= status,
+	.error_handler	= error,
+	.hot_add_disk	= raid10_add_disk,
+	.hot_remove_disk= raid10_remove_disk,
+	.spare_active	= raid10_spare_active,
+	.sync_request	= sync_request,
+};
+
+static int __init raid_init(void)
+{
+	return register_md_personality(RAID10, &raid10_personality);
+}
+
+static void raid_exit(void)
+{
+	unregister_md_personality(RAID10);
+}
+
+module_init(raid_init);
+module_exit(raid_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("md-personality-9"); /* RAID10 */
diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c
--- a/drivers/md/raid5.c	2004-08-23 01:14:46 -07:00
+++ b/drivers/md/raid5.c	2004-08-24 02:08:45 -07:00
@@ -1071,7 +1071,8 @@
 					PRINTK("Reading block %d (sync=%d)\n", 
 						i, syncing);
 					if (syncing)
-						md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS);
+						md_sync_acct(conf->disks[i].rdev->bdev,
+							     STRIPE_SECTORS);
 				}
 			}
 		}
@@ -1256,7 +1257,7 @@
  
 		if (rdev) {
 			if (test_bit(R5_Syncio, &sh->dev[i].flags))
-				md_sync_acct(rdev, STRIPE_SECTORS);
+				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
 			bi->bi_bdev = rdev->bdev;
 			PRINTK("for %llu schedule op %ld on disc %d\n",
diff -Nru a/drivers/md/raid6main.c b/drivers/md/raid6main.c
--- a/drivers/md/raid6main.c	2004-08-23 01:14:46 -07:00
+++ b/drivers/md/raid6main.c	2004-08-24 02:08:45 -07:00
@@ -1208,7 +1208,8 @@
 					PRINTK("Reading block %d (sync=%d)\n",
 						i, syncing);
 					if (syncing)
-						md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS);
+						md_sync_acct(conf->disks[i].rdev->bdev,
+							     STRIPE_SECTORS);
 				}
 			}
 		}
@@ -1418,7 +1419,7 @@
 
 		if (rdev) {
 			if (test_bit(R5_Syncio, &sh->dev[i].flags))
-				md_sync_acct(rdev, STRIPE_SECTORS);
+				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
 			bi->bi_bdev = rdev->bdev;
 			PRINTK("for %llu schedule op %ld on disc %d\n",
diff -Nru a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
--- a/drivers/media/dvb/bt8xx/bt878.c	2003-12-30 00:40:50 -08:00
+++ b/drivers/media/dvb/bt8xx/bt878.c	2004-08-27 13:05:05 -07:00
@@ -417,6 +417,8 @@
 
 	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
 	       bt878_num);
+	if (pci_enable_device(dev))
+		return -EIO;
 
 	bt = &bt878[bt878_num];
 	bt->dev = dev;
@@ -426,11 +428,10 @@
 	bt->id = dev->device;
 	bt->irq = dev->irq;
 	bt->bt878_adr = pci_resource_start(dev, 0);
-	if (pci_enable_device(dev))
-		return -EIO;
 	if (!request_mem_region(pci_resource_start(dev, 0),
 				pci_resource_len(dev, 0), "bt878")) {
-		return -EBUSY;
+		result = -EBUSY;
+		goto fail0;
 	}
 
 	pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
@@ -501,6 +502,8 @@
       fail1:
 	release_mem_region(pci_resource_start(bt->dev, 0),
 			   pci_resource_len(bt->dev, 0));
+      fail0:
+	pci_disable_device(dev);
 	return result;
 }
 
@@ -517,7 +520,7 @@
 
 	/* first disable interrupts before unmapping the memory! */
 	btwrite(0, BT878_AINT_MASK);
-	btwrite(~0x0UL, BT878_AINT_STAT);
+	btwrite(~0U, BT878_AINT_STAT);
 
 	/* disable PCI bus-mastering */
 	pci_read_config_byte(bt->dev, PCI_COMMAND, &command);
@@ -540,6 +543,7 @@
 	bt878_mem_free(bt);
 
 	pci_set_drvdata(pci_dev, NULL);
+	pci_disable_device(pci_dev);
 	return;
 }
 
diff -Nru a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c	2004-07-13 06:27:49 -07:00
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c	2004-08-25 18:53:12 -07:00
@@ -1196,7 +1196,7 @@
         int status;
         char fragbuf[HOST_LINK_BUF_SIZE];
         int fragpos = 0;
-        int fraglen;
+        size_t fraglen;
         unsigned long timeout;
         int written;
 
@@ -1257,7 +1257,7 @@
         int slot;
         int slot_count = 0;
         int idx;
-        int fraglen;
+        size_t fraglen;
         int connection_id = -1;
         int found = 0;
         u8 hdr[2];
diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
--- a/drivers/media/dvb/dvb-core/dvb_net.c	2004-07-16 07:15:18 -07:00
+++ b/drivers/media/dvb/dvb-core/dvb_net.c	2004-08-25 18:53:20 -07:00
@@ -563,7 +563,7 @@
 	if (buffer2 != 0)
 		printk(KERN_WARNING "buffer2 not 0: %p.\n", buffer2);
 	if (buffer1_len > 32768)
-		printk(KERN_WARNING "length > 32k: %u.\n", buffer1_len);
+		printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);
 	/* printk("TS callback: %u bytes, %u TS cells @ %p.\n",
 	          buffer1_len, buffer1_len / TS_SZ, buffer1); */
 	dvb_net_ule(dev, buffer1, buffer1_len);
diff -Nru a/drivers/media/dvb/frontends/dst.c b/drivers/media/dvb/frontends/dst.c
--- a/drivers/media/dvb/frontends/dst.c	2004-03-11 10:40:44 -08:00
+++ b/drivers/media/dvb/frontends/dst.c	2004-08-27 13:05:05 -07:00
@@ -1145,8 +1145,8 @@
 	}
 
 	dst_init (dst);
-	dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, 
-			(u32)dst, (u32)(dst->bt), (u32)(dst->i2c));
+	dprintk("%s: register dst %p bt %p i2c %p\n", __FUNCTION__, 
+			dst, dst->bt, dst->i2c);
 
 	info = &dst_info_sat;
 	if (dst->dst_type == DST_TYPE_IS_TERR)
@@ -1162,7 +1162,7 @@
 static void dst_detach (struct dvb_i2c_bus *i2c, void *data)
 {
 	dvb_unregister_frontend (dst_ioctl, i2c);
-	dprintk("%s: unregister dst %8.8x\n", __FUNCTION__, (u32)(data));
+	dprintk("%s: unregister dst %p\n", __FUNCTION__, data);
 	if (data)
 		kfree(data);
 }
diff -Nru a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
--- a/drivers/media/dvb/ttpci/Kconfig	2004-01-26 03:19:59 -08:00
+++ b/drivers/media/dvb/ttpci/Kconfig	2004-08-24 02:08:59 -07:00
@@ -1,6 +1,6 @@
 config DVB_AV7110
 	tristate "AV7110 cards"
-	depends on DVB_CORE
+	depends on DVB_CORE && PCI
 	select FW_LOADER
 	select VIDEO_DEV
 	select VIDEO_SAA7146_VV
@@ -45,7 +45,7 @@
 
 config DVB_BUDGET
 	tristate "Budget cards"
-	depends on DVB_CORE
+	depends on DVB_CORE && PCI
 	select VIDEO_SAA7146
 	help
 	  Support for simple SAA7146 based DVB cards
@@ -59,7 +59,7 @@
 
 config DVB_BUDGET_CI
 	tristate "Budget cards with onboard CI connector"
-	depends on DVB_CORE
+	depends on DVB_CORE && PCI
 	select VIDEO_SAA7146
 	help
 	  Support for simple SAA7146 based DVB cards
@@ -76,7 +76,7 @@
 
 config DVB_BUDGET_AV
 	tristate "Budget cards with analog video inputs"
-	depends on DVB_CORE
+	depends on DVB_CORE && PCI
 	select VIDEO_DEV
 	select VIDEO_SAA7146_VV
 	help
diff -Nru a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-07-13 06:27:50 -07:00
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-08-25 18:53:44 -07:00
@@ -1181,7 +1181,7 @@
 	firmware_size = fw_entry->size;
 
 	if (firmware_size < 60) {
-		printk("%s: firmware size too small for DSP code (%u < 60).\n",
+		printk("%s: firmware size too small for DSP code (%zu < 60).\n",
 			__FUNCTION__, firmware_size);
 		return -1;
 	}
diff -Nru a/drivers/media/video/meye.c b/drivers/media/video/meye.c
--- a/drivers/media/video/meye.c	2004-07-12 01:01:06 -07:00
+++ b/drivers/media/video/meye.c	2004-08-25 10:34:12 -07:00
@@ -58,7 +58,7 @@
 static inline void meye_initq(struct meye_queue *queue) {
 	queue->head = queue->tail = 0;
 	queue->len = 0;
-	queue->s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
+	queue->s_lock = SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&queue->proc_list);
 }
 
diff -Nru a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
--- a/drivers/media/video/zoran_driver.c	2004-07-12 01:01:15 -07:00
+++ b/drivers/media/video/zoran_driver.c	2004-08-27 13:05:05 -07:00
@@ -2265,8 +2265,8 @@
 
 		dprintk(3,
 			KERN_DEBUG
-			"%s: VIDIOCSFBUF - base=0x%x, w=%d, h=%d, depth=%d, bpl=%d\n",
-			ZR_DEVNAME(zr), (u32) vbuf->base, vbuf->width,
+			"%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n",
+			ZR_DEVNAME(zr), vbuf->base, vbuf->width,
 			vbuf->height, vbuf->depth, vbuf->bytesperline);
 
 		for (i = 0; i < zoran_num_formats; i++)
diff -Nru a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
--- a/drivers/message/fusion/Kconfig	2004-05-10 04:25:43 -07:00
+++ b/drivers/message/fusion/Kconfig	2004-07-13 14:55:06 -07:00
@@ -27,39 +27,6 @@
 	  necessary (or recommended) unless the user will be running 
 	  large I/O's via the raw interface.
 
-config FUSION_ISENSE
-	tristate "Enhanced SCSI error reporting"
-	depends on MODULES && FUSION && m
-	---help---
-	  The isense module (roughly stands for Interpret SENSE data) is
-	  completely optional.  It simply provides extra English readable
-	  strings in SCSI Error Report(s) that might be generated from the
-	  Fusion MPT SCSI Host driver, for example when a target device
-	  returns a SCSI check condition on a I/O.  Without this module
-	  loaded you might see:
-
-	  SCSI Error Report =-=-= (ioc0,scsi5:0)
-	  SCSI_Status=02h (CHECK_CONDITION)
-	  Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00
-	  SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
-	  SenseKey=2h (NOT READY); FRU=02h
-	  ASC/ASCQ=29h/00h
-
-	  Where otherwise, if this module had been loaded, you would see:
-
-	  SCSI Error Report =-=-= (ioc0,scsi5:0)
-	  SCSI_Status=02h (CHECK_CONDITION)
-	  Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 - "WRITE(10)"
-	  SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
-	  SenseKey=2h (NOT READY); FRU=02h
-	  ASC/ASCQ=29h/00h "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED"
-
-	  Say M for "Enhanced SCSI error reporting" to compile this optional module,
-	  creating a driver named: isense.
-
-	  NOTE: Support for building this feature into the kernel is not
-	  available, due to kernel size considerations.
-
 config FUSION_CTL
 	tristate "Fusion MPT misc device (ioctl) driver"
 	depends on MODULES && FUSION && m
diff -Nru a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
--- a/drivers/message/fusion/Makefile	2004-03-27 07:38:07 -08:00
+++ b/drivers/message/fusion/Makefile	2004-07-13 14:33:18 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers.
 #
 # Note! If you want to turn on various debug defines for an extended period of
-# time but don't want them lingering around in the Makefile when you pass it on 
+# time but don't want them lingering around in the Makefile when you pass it on
 # to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC
@@ -48,6 +48,5 @@
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
 
 obj-$(CONFIG_FUSION)		+= mptbase.o mptscsih.o
-obj-$(CONFIG_FUSION_ISENSE)	+= isense.o
 obj-$(CONFIG_FUSION_CTL)	+= mptctl.o
 obj-$(CONFIG_FUSION_LAN)	+= mptlan.o
diff -Nru a/drivers/message/fusion/ascq_tbl.c b/drivers/message/fusion/ascq_tbl.c
--- a/drivers/message/fusion/ascq_tbl.c	2002-02-05 11:10:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,2416 +0,0 @@
-#ifndef SCSI_ASCQ_TBL_C_INCLUDED
-#define SCSI_ASCQ_TBL_C_INCLUDED
-
-/* AuToMaGiCaLlY generated from: "t10.org/asc-num.txt"
- *******************************************************************************
- * File: ASC-NUM.TXT
- * 
- * SCSI ASC/ASCQ Assignments
- * Numeric Sorted Listing
- * as of  5/18/00
- * 
- *          D - DIRECT ACCESS DEVICE (SBC-2)                   device column key
- *          .T - SEQUENTIAL ACCESS DEVICE (SSC)               -------------------
- *          . L - PRINTER DEVICE (SSC)                           blank = reserved
- *          .  P - PROCESSOR DEVICE (SPC)                     not blank = allowed
- *          .  .W - WRITE ONCE READ MULTIPLE DEVICE (SBC-2)
- *          .  . R - CD DEVICE (MMC)
- *          .  .  S - SCANNER DEVICE (SCSI-2)
- *          .  .  .O - OPTICAL MEMORY DEVICE (SBC-2)
- *          .  .  . M - MEDIA CHANGER DEVICE (SMC)
- *          .  .  .  C - COMMUNICATION DEVICE (SCSI-2)
- *          .  .  .  .A - STORAGE ARRAY DEVICE (SCC)
- *          .  .  .  . E - ENCLOSURE SERVICES DEVICE (SES)
- *          .  .  .  .  B - SIMPLIFIED DIRECT-ACCESS DEVICE (RBC)
- *          .  .  .  .  .K - OPTICAL CARD READER/WRITER DEVICE (OCRW)
- * ASC/ASCQ DTLPWRSOMCAEBK  Description
- * -------  --------------  ----------------------------------------------------
- */
-
-static char SenseDevTypes001[] = "DTLPWRSOMCAEBK";
-static char SenseDevTypes002[] = ".T............";
-static char SenseDevTypes003[] = ".T....S.......";
-static char SenseDevTypes004[] = ".TL...S.......";
-static char SenseDevTypes005[] = ".....R........";
-static char SenseDevTypes006[] = "DTL.WRSOM.AEBK";
-static char SenseDevTypes007[] = "D...W..O....BK";
-static char SenseDevTypes008[] = "D...WR.OM...BK";
-static char SenseDevTypes009[] = "DTL.W.SO....BK";
-static char SenseDevTypes010[] = "DTL..R.O....B.";
-static char SenseDevTypes011[] = "DT..W..OMCA.BK";
-static char SenseDevTypes012[] = "..............";
-static char SenseDevTypes013[] = "DTL.WRSOMCAEBK";
-static char SenseDevTypes014[] = "DTL.WRSOM...BK";
-static char SenseDevTypes015[] = "DT...R.OM...BK";
-static char SenseDevTypes016[] = "DTLPWRSO.C...K";
-static char SenseDevTypes017[] = "DT..WR.O....B.";
-static char SenseDevTypes018[] = "....WR.O.....K";
-static char SenseDevTypes019[] = "....WR.O......";
-static char SenseDevTypes020[] = ".T...RS.......";
-static char SenseDevTypes021[] = ".............K";
-static char SenseDevTypes022[] = "DT..W..O....B.";
-static char SenseDevTypes023[] = "DT..WRSO....BK";
-static char SenseDevTypes024[] = "DT..W.SO....BK";
-static char SenseDevTypes025[] = "....WR.O....B.";
-static char SenseDevTypes026[] = "....W..O....B.";
-static char SenseDevTypes027[] = "DT.....O....BK";
-static char SenseDevTypes028[] = "DTL.WRSO....BK";
-static char SenseDevTypes029[] = "DT..WR.O....BK";
-static char SenseDevTypes030[] = "DT..W..O....BK";
-static char SenseDevTypes031[] = "D...WR.O....BK";
-static char SenseDevTypes032[] = "D......O.....K";
-static char SenseDevTypes033[] = "D......O....BK";
-static char SenseDevTypes034[] = "DT..WR.OM...BK";
-static char SenseDevTypes035[] = "D.............";
-static char SenseDevTypes036[] = "DTLPWRSOMCAE.K";
-static char SenseDevTypes037[] = "DTLPWRSOMCA.BK";
-static char SenseDevTypes038[] = ".T...R........";
-static char SenseDevTypes039[] = "DT..WR.OM...B.";
-static char SenseDevTypes040[] = "DTL.WRSOMCAE.K";
-static char SenseDevTypes041[] = "DTLPWRSOMCAE..";
-static char SenseDevTypes042[] = "......S.......";
-static char SenseDevTypes043[] = "............B.";
-static char SenseDevTypes044[] = "DTLPWRSO.CA..K";
-static char SenseDevTypes045[] = "DT...R.......K";
-static char SenseDevTypes046[] = "D.L..R.O....B.";
-static char SenseDevTypes047[] = "..L...........";
-static char SenseDevTypes048[] = ".TL...........";
-static char SenseDevTypes049[] = "DTLPWRSOMC..BK";
-static char SenseDevTypes050[] = "DT..WR.OMCAEBK";
-static char SenseDevTypes051[] = "DT..WR.OMCAEB.";
-static char SenseDevTypes052[] = ".T...R.O......";
-static char SenseDevTypes053[] = "...P..........";
-static char SenseDevTypes054[] = "DTLPWRSOM.AE.K";
-static char SenseDevTypes055[] = "DTLPWRSOM.AE..";
-static char SenseDevTypes056[] = ".......O......";
-static char SenseDevTypes057[] = "DTLPWRSOM...BK";
-static char SenseDevTypes058[] = "DT..WR.O..A.BK";
-static char SenseDevTypes059[] = "DTLPWRSOM....K";
-static char SenseDevTypes060[] = "D......O......";
-static char SenseDevTypes061[] = ".....R......B.";
-static char SenseDevTypes062[] = "D...........B.";
-static char SenseDevTypes063[] = "............BK";
-static char SenseDevTypes064[] = "..........A...";
-
-static ASCQ_Table_t ASCQ_Table[] = {
-  {
-    0x00, 0x00,
-    SenseDevTypes001,
-    "NO ADDITIONAL SENSE INFORMATION"
-  },
-  {
-    0x00, 0x01,
-    SenseDevTypes002,
-    "FILEMARK DETECTED"
-  },
-  {
-    0x00, 0x02,
-    SenseDevTypes003,
-    "END-OF-PARTITION/MEDIUM DETECTED"
-  },
-  {
-    0x00, 0x03,
-    SenseDevTypes002,
-    "SETMARK DETECTED"
-  },
-  {
-    0x00, 0x04,
-    SenseDevTypes003,
-    "BEGINNING-OF-PARTITION/MEDIUM DETECTED"
-  },
-  {
-    0x00, 0x05,
-    SenseDevTypes004,
-    "END-OF-DATA DETECTED"
-  },
-  {
-    0x00, 0x06,
-    SenseDevTypes001,
-    "I/O PROCESS TERMINATED"
-  },
-  {
-    0x00, 0x11,
-    SenseDevTypes005,
-    "AUDIO PLAY OPERATION IN PROGRESS"
-  },
-  {
-    0x00, 0x12,
-    SenseDevTypes005,
-    "AUDIO PLAY OPERATION PAUSED"
-  },
-  {
-    0x00, 0x13,
-    SenseDevTypes005,
-    "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED"
-  },
-  {
-    0x00, 0x14,
-    SenseDevTypes005,
-    "AUDIO PLAY OPERATION STOPPED DUE TO ERROR"
-  },
-  {
-    0x00, 0x15,
-    SenseDevTypes005,
-    "NO CURRENT AUDIO STATUS TO RETURN"
-  },
-  {
-    0x00, 0x16,
-    SenseDevTypes001,
-    "OPERATION IN PROGRESS"
-  },
-  {
-    0x00, 0x17,
-    SenseDevTypes006,
-    "CLEANING REQUESTED"
-  },
-  {
-    0x01, 0x00,
-    SenseDevTypes007,
-    "NO INDEX/SECTOR SIGNAL"
-  },
-  {
-    0x02, 0x00,
-    SenseDevTypes008,
-    "NO SEEK COMPLETE"
-  },
-  {
-    0x03, 0x00,
-    SenseDevTypes009,
-    "PERIPHERAL DEVICE WRITE FAULT"
-  },
-  {
-    0x03, 0x01,
-    SenseDevTypes002,
-    "NO WRITE CURRENT"
-  },
-  {
-    0x03, 0x02,
-    SenseDevTypes002,
-    "EXCESSIVE WRITE ERRORS"
-  },
-  {
-    0x04, 0x00,
-    SenseDevTypes001,
-    "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE"
-  },
-  {
-    0x04, 0x01,
-    SenseDevTypes001,
-    "LOGICAL UNIT IS IN PROCESS OF BECOMING READY"
-  },
-  {
-    0x04, 0x02,
-    SenseDevTypes001,
-    "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED"
-  },
-  {
-    0x04, 0x03,
-    SenseDevTypes001,
-    "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED"
-  },
-  {
-    0x04, 0x04,
-    SenseDevTypes010,
-    "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS"
-  },
-  {
-    0x04, 0x05,
-    SenseDevTypes011,
-    "LOGICAL UNIT NOT READY, REBUILD IN PROGRESS"
-  },
-  {
-    0x04, 0x06,
-    SenseDevTypes011,
-    "LOGICAL UNIT NOT READY, RECALCULATION IN PROGRESS"
-  },
-  {
-    0x04, 0x07,
-    SenseDevTypes001,
-    "LOGICAL UNIT NOT READY, OPERATION IN PROGRESS"
-  },
-  {
-    0x04, 0x08,
-    SenseDevTypes005,
-    "LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS"
-  },
-  {
-    0x04, 0x09,
-    SenseDevTypes001,
-    "LOGICAL UNIT NOT READY, SELF-TEST IN PROGRESS"
-  },
-  {
-    0x04, 0x10,
-    SenseDevTypes012,
-    "auxiliary memory code 2 (99-148) [proposed]"
-  },
-  {
-    0x05, 0x00,
-    SenseDevTypes013,
-    "LOGICAL UNIT DOES NOT RESPOND TO SELECTION"
-  },
-  {
-    0x06, 0x00,
-    SenseDevTypes008,
-    "NO REFERENCE POSITION FOUND"
-  },
-  {
-    0x07, 0x00,
-    SenseDevTypes014,
-    "MULTIPLE PERIPHERAL DEVICES SELECTED"
-  },
-  {
-    0x08, 0x00,
-    SenseDevTypes013,
-    "LOGICAL UNIT COMMUNICATION FAILURE"
-  },
-  {
-    0x08, 0x01,
-    SenseDevTypes013,
-    "LOGICAL UNIT COMMUNICATION TIME-OUT"
-  },
-  {
-    0x08, 0x02,
-    SenseDevTypes013,
-    "LOGICAL UNIT COMMUNICATION PARITY ERROR"
-  },
-  {
-    0x08, 0x03,
-    SenseDevTypes015,
-    "LOGICAL UNIT COMMUNICATION CRC ERROR (ULTRA-DMA/32)"
-  },
-  {
-    0x08, 0x04,
-    SenseDevTypes016,
-    "UNREACHABLE COPY TARGET"
-  },
-  {
-    0x09, 0x00,
-    SenseDevTypes017,
-    "TRACK FOLLOWING ERROR"
-  },
-  {
-    0x09, 0x01,
-    SenseDevTypes018,
-    "TRACKING SERVO FAILURE"
-  },
-  {
-    0x09, 0x02,
-    SenseDevTypes018,
-    "FOCUS SERVO FAILURE"
-  },
-  {
-    0x09, 0x03,
-    SenseDevTypes019,
-    "SPINDLE SERVO FAILURE"
-  },
-  {
-    0x09, 0x04,
-    SenseDevTypes017,
-    "HEAD SELECT FAULT"
-  },
-  {
-    0x0A, 0x00,
-    SenseDevTypes001,
-    "ERROR LOG OVERFLOW"
-  },
-  {
-    0x0B, 0x00,
-    SenseDevTypes001,
-    "WARNING"
-  },
-  {
-    0x0B, 0x01,
-    SenseDevTypes001,
-    "WARNING - SPECIFIED TEMPERATURE EXCEEDED"
-  },
-  {
-    0x0B, 0x02,
-    SenseDevTypes001,
-    "WARNING - ENCLOSURE DEGRADED"
-  },
-  {
-    0x0C, 0x00,
-    SenseDevTypes020,
-    "WRITE ERROR"
-  },
-  {
-    0x0C, 0x01,
-    SenseDevTypes021,
-    "WRITE ERROR - RECOVERED WITH AUTO REALLOCATION"
-  },
-  {
-    0x0C, 0x02,
-    SenseDevTypes007,
-    "WRITE ERROR - AUTO REALLOCATION FAILED"
-  },
-  {
-    0x0C, 0x03,
-    SenseDevTypes007,
-    "WRITE ERROR - RECOMMEND REASSIGNMENT"
-  },
-  {
-    0x0C, 0x04,
-    SenseDevTypes022,
-    "COMPRESSION CHECK MISCOMPARE ERROR"
-  },
-  {
-    0x0C, 0x05,
-    SenseDevTypes022,
-    "DATA EXPANSION OCCURRED DURING COMPRESSION"
-  },
-  {
-    0x0C, 0x06,
-    SenseDevTypes022,
-    "BLOCK NOT COMPRESSIBLE"
-  },
-  {
-    0x0C, 0x07,
-    SenseDevTypes005,
-    "WRITE ERROR - RECOVERY NEEDED"
-  },
-  {
-    0x0C, 0x08,
-    SenseDevTypes005,
-    "WRITE ERROR - RECOVERY FAILED"
-  },
-  {
-    0x0C, 0x09,
-    SenseDevTypes005,
-    "WRITE ERROR - LOSS OF STREAMING"
-  },
-  {
-    0x0C, 0x0A,
-    SenseDevTypes005,
-    "WRITE ERROR - PADDING BLOCKS ADDED"
-  },
-  {
-    0x0C, 0x0B,
-    SenseDevTypes012,
-    "auxiliary memory code 4 (99-148) [proposed]"
-  },
-  {
-    0x10, 0x00,
-    SenseDevTypes007,
-    "ID CRC OR ECC ERROR"
-  },
-  {
-    0x11, 0x00,
-    SenseDevTypes023,
-    "UNRECOVERED READ ERROR"
-  },
-  {
-    0x11, 0x01,
-    SenseDevTypes023,
-    "READ RETRIES EXHAUSTED"
-  },
-  {
-    0x11, 0x02,
-    SenseDevTypes023,
-    "ERROR TOO LONG TO CORRECT"
-  },
-  {
-    0x11, 0x03,
-    SenseDevTypes024,
-    "MULTIPLE READ ERRORS"
-  },
-  {
-    0x11, 0x04,
-    SenseDevTypes007,
-    "UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED"
-  },
-  {
-    0x11, 0x05,
-    SenseDevTypes025,
-    "L-EC UNCORRECTABLE ERROR"
-  },
-  {
-    0x11, 0x06,
-    SenseDevTypes025,
-    "CIRC UNRECOVERED ERROR"
-  },
-  {
-    0x11, 0x07,
-    SenseDevTypes026,
-    "DATA RE-SYNCHRONIZATION ERROR"
-  },
-  {
-    0x11, 0x08,
-    SenseDevTypes002,
-    "INCOMPLETE BLOCK READ"
-  },
-  {
-    0x11, 0x09,
-    SenseDevTypes002,
-    "NO GAP FOUND"
-  },
-  {
-    0x11, 0x0A,
-    SenseDevTypes027,
-    "MISCORRECTED ERROR"
-  },
-  {
-    0x11, 0x0B,
-    SenseDevTypes007,
-    "UNRECOVERED READ ERROR - RECOMMEND REASSIGNMENT"
-  },
-  {
-    0x11, 0x0C,
-    SenseDevTypes007,
-    "UNRECOVERED READ ERROR - RECOMMEND REWRITE THE DATA"
-  },
-  {
-    0x11, 0x0D,
-    SenseDevTypes017,
-    "DE-COMPRESSION CRC ERROR"
-  },
-  {
-    0x11, 0x0E,
-    SenseDevTypes017,
-    "CANNOT DECOMPRESS USING DECLARED ALGORITHM"
-  },
-  {
-    0x11, 0x0F,
-    SenseDevTypes005,
-    "ERROR READING UPC/EAN NUMBER"
-  },
-  {
-    0x11, 0x10,
-    SenseDevTypes005,
-    "ERROR READING ISRC NUMBER"
-  },
-  {
-    0x11, 0x11,
-    SenseDevTypes005,
-    "READ ERROR - LOSS OF STREAMING"
-  },
-  {
-    0x11, 0x12,
-    SenseDevTypes012,
-    "auxiliary memory code 3 (99-148) [proposed]"
-  },
-  {
-    0x12, 0x00,
-    SenseDevTypes007,
-    "ADDRESS MARK NOT FOUND FOR ID FIELD"
-  },
-  {
-    0x13, 0x00,
-    SenseDevTypes007,
-    "ADDRESS MARK NOT FOUND FOR DATA FIELD"
-  },
-  {
-    0x14, 0x00,
-    SenseDevTypes028,
-    "RECORDED ENTITY NOT FOUND"
-  },
-  {
-    0x14, 0x01,
-    SenseDevTypes029,
-    "RECORD NOT FOUND"
-  },
-  {
-    0x14, 0x02,
-    SenseDevTypes002,
-    "FILEMARK OR SETMARK NOT FOUND"
-  },
-  {
-    0x14, 0x03,
-    SenseDevTypes002,
-    "END-OF-DATA NOT FOUND"
-  },
-  {
-    0x14, 0x04,
-    SenseDevTypes002,
-    "BLOCK SEQUENCE ERROR"
-  },
-  {
-    0x14, 0x05,
-    SenseDevTypes030,
-    "RECORD NOT FOUND - RECOMMEND REASSIGNMENT"
-  },
-  {
-    0x14, 0x06,
-    SenseDevTypes030,
-    "RECORD NOT FOUND - DATA AUTO-REALLOCATED"
-  },
-  {
-    0x15, 0x00,
-    SenseDevTypes014,
-    "RANDOM POSITIONING ERROR"
-  },
-  {
-    0x15, 0x01,
-    SenseDevTypes014,
-    "MECHANICAL POSITIONING ERROR"
-  },
-  {
-    0x15, 0x02,
-    SenseDevTypes029,
-    "POSITIONING ERROR DETECTED BY READ OF MEDIUM"
-  },
-  {
-    0x16, 0x00,
-    SenseDevTypes007,
-    "DATA SYNCHRONIZATION MARK ERROR"
-  },
-  {
-    0x16, 0x01,
-    SenseDevTypes007,
-    "DATA SYNC ERROR - DATA REWRITTEN"
-  },
-  {
-    0x16, 0x02,
-    SenseDevTypes007,
-    "DATA SYNC ERROR - RECOMMEND REWRITE"
-  },
-  {
-    0x16, 0x03,
-    SenseDevTypes007,
-    "DATA SYNC ERROR - DATA AUTO-REALLOCATED"
-  },
-  {
-    0x16, 0x04,
-    SenseDevTypes007,
-    "DATA SYNC ERROR - RECOMMEND REASSIGNMENT"
-  },
-  {
-    0x17, 0x00,
-    SenseDevTypes023,
-    "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED"
-  },
-  {
-    0x17, 0x01,
-    SenseDevTypes023,
-    "RECOVERED DATA WITH RETRIES"
-  },
-  {
-    0x17, 0x02,
-    SenseDevTypes029,
-    "RECOVERED DATA WITH POSITIVE HEAD OFFSET"
-  },
-  {
-    0x17, 0x03,
-    SenseDevTypes029,
-    "RECOVERED DATA WITH NEGATIVE HEAD OFFSET"
-  },
-  {
-    0x17, 0x04,
-    SenseDevTypes025,
-    "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED"
-  },
-  {
-    0x17, 0x05,
-    SenseDevTypes031,
-    "RECOVERED DATA USING PREVIOUS SECTOR ID"
-  },
-  {
-    0x17, 0x06,
-    SenseDevTypes007,
-    "RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED"
-  },
-  {
-    0x17, 0x07,
-    SenseDevTypes031,
-    "RECOVERED DATA WITHOUT ECC - RECOMMEND REASSIGNMENT"
-  },
-  {
-    0x17, 0x08,
-    SenseDevTypes031,
-    "RECOVERED DATA WITHOUT ECC - RECOMMEND REWRITE"
-  },
-  {
-    0x17, 0x09,
-    SenseDevTypes031,
-    "RECOVERED DATA WITHOUT ECC - DATA REWRITTEN"
-  },
-  {
-    0x18, 0x00,
-    SenseDevTypes029,
-    "RECOVERED DATA WITH ERROR CORRECTION APPLIED"
-  },
-  {
-    0x18, 0x01,
-    SenseDevTypes031,
-    "RECOVERED DATA WITH ERROR CORR. & RETRIES APPLIED"
-  },
-  {
-    0x18, 0x02,
-    SenseDevTypes031,
-    "RECOVERED DATA - DATA AUTO-REALLOCATED"
-  },
-  {
-    0x18, 0x03,
-    SenseDevTypes005,
-    "RECOVERED DATA WITH CIRC"
-  },
-  {
-    0x18, 0x04,
-    SenseDevTypes005,
-    "RECOVERED DATA WITH L-EC"
-  },
-  {
-    0x18, 0x05,
-    SenseDevTypes031,
-    "RECOVERED DATA - RECOMMEND REASSIGNMENT"
-  },
-  {
-    0x18, 0x06,
-    SenseDevTypes031,
-    "RECOVERED DATA - RECOMMEND REWRITE"
-  },
-  {
-    0x18, 0x07,
-    SenseDevTypes007,
-    "RECOVERED DATA WITH ECC - DATA REWRITTEN"
-  },
-  {
-    0x19, 0x00,
-    SenseDevTypes032,
-    "DEFECT LIST ERROR"
-  },
-  {
-    0x19, 0x01,
-    SenseDevTypes032,
-    "DEFECT LIST NOT AVAILABLE"
-  },
-  {
-    0x19, 0x02,
-    SenseDevTypes032,
-    "DEFECT LIST ERROR IN PRIMARY LIST"
-  },
-  {
-    0x19, 0x03,
-    SenseDevTypes032,
-    "DEFECT LIST ERROR IN GROWN LIST"
-  },
-  {
-    0x1A, 0x00,
-    SenseDevTypes001,
-    "PARAMETER LIST LENGTH ERROR"
-  },
-  {
-    0x1B, 0x00,
-    SenseDevTypes001,
-    "SYNCHRONOUS DATA TRANSFER ERROR"
-  },
-  {
-    0x1C, 0x00,
-    SenseDevTypes033,
-    "DEFECT LIST NOT FOUND"
-  },
-  {
-    0x1C, 0x01,
-    SenseDevTypes033,
-    "PRIMARY DEFECT LIST NOT FOUND"
-  },
-  {
-    0x1C, 0x02,
-    SenseDevTypes033,
-    "GROWN DEFECT LIST NOT FOUND"
-  },
-  {
-    0x1D, 0x00,
-    SenseDevTypes029,
-    "MISCOMPARE DURING VERIFY OPERATION"
-  },
-  {
-    0x1E, 0x00,
-    SenseDevTypes007,
-    "RECOVERED ID WITH ECC CORRECTION"
-  },
-  {
-    0x1F, 0x00,
-    SenseDevTypes032,
-    "PARTIAL DEFECT LIST TRANSFER"
-  },
-  {
-    0x20, 0x00,
-    SenseDevTypes001,
-    "INVALID COMMAND OPERATION CODE"
-  },
-  {
-    0x20, 0x01,
-    SenseDevTypes012,
-    "access controls code 1 (99-314) [proposed]"
-  },
-  {
-    0x20, 0x02,
-    SenseDevTypes012,
-    "access controls code 2 (99-314) [proposed]"
-  },
-  {
-    0x20, 0x03,
-    SenseDevTypes012,
-    "access controls code 3 (99-314) [proposed]"
-  },
-  {
-    0x21, 0x00,
-    SenseDevTypes034,
-    "LOGICAL BLOCK ADDRESS OUT OF RANGE"
-  },
-  {
-    0x21, 0x01,
-    SenseDevTypes034,
-    "INVALID ELEMENT ADDRESS"
-  },
-  {
-    0x22, 0x00,
-    SenseDevTypes035,
-    "ILLEGAL FUNCTION (USE 20 00, 24 00, OR 26 00)"
-  },
-  {
-    0x24, 0x00,
-    SenseDevTypes001,
-    "INVALID FIELD IN CDB"
-  },
-  {
-    0x24, 0x01,
-    SenseDevTypes001,
-    "CDB DECRYPTION ERROR"
-  },
-  {
-    0x25, 0x00,
-    SenseDevTypes001,
-    "LOGICAL UNIT NOT SUPPORTED"
-  },
-  {
-    0x26, 0x00,
-    SenseDevTypes001,
-    "INVALID FIELD IN PARAMETER LIST"
-  },
-  {
-    0x26, 0x01,
-    SenseDevTypes001,
-    "PARAMETER NOT SUPPORTED"
-  },
-  {
-    0x26, 0x02,
-    SenseDevTypes001,
-    "PARAMETER VALUE INVALID"
-  },
-  {
-    0x26, 0x03,
-    SenseDevTypes036,
-    "THRESHOLD PARAMETERS NOT SUPPORTED"
-  },
-  {
-    0x26, 0x04,
-    SenseDevTypes001,
-    "INVALID RELEASE OF PERSISTENT RESERVATION"
-  },
-  {
-    0x26, 0x05,
-    SenseDevTypes037,
-    "DATA DECRYPTION ERROR"
-  },
-  {
-    0x26, 0x06,
-    SenseDevTypes016,
-    "TOO MANY TARGET DESCRIPTORS"
-  },
-  {
-    0x26, 0x07,
-    SenseDevTypes016,
-    "UNSUPPORTED TARGET DESCRIPTOR TYPE CODE"
-  },
-  {
-    0x26, 0x08,
-    SenseDevTypes016,
-    "TOO MANY SEGMENT DESCRIPTORS"
-  },
-  {
-    0x26, 0x09,
-    SenseDevTypes016,
-    "UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE"
-  },
-  {
-    0x26, 0x0A,
-    SenseDevTypes016,
-    "UNEXPECTED INEXACT SEGMENT"
-  },
-  {
-    0x26, 0x0B,
-    SenseDevTypes016,
-    "INLINE DATA LENGTH EXCEEDED"
-  },
-  {
-    0x26, 0x0C,
-    SenseDevTypes016,
-    "INVALID OPERATION FOR COPY SOURCE OR DESTINATION"
-  },
-  {
-    0x26, 0x0D,
-    SenseDevTypes016,
-    "COPY SEGMENT GRANULARITY VIOLATION"
-  },
-  {
-    0x27, 0x00,
-    SenseDevTypes029,
-    "WRITE PROTECTED"
-  },
-  {
-    0x27, 0x01,
-    SenseDevTypes029,
-    "HARDWARE WRITE PROTECTED"
-  },
-  {
-    0x27, 0x02,
-    SenseDevTypes029,
-    "LOGICAL UNIT SOFTWARE WRITE PROTECTED"
-  },
-  {
-    0x27, 0x03,
-    SenseDevTypes038,
-    "ASSOCIATED WRITE PROTECT"
-  },
-  {
-    0x27, 0x04,
-    SenseDevTypes038,
-    "PERSISTENT WRITE PROTECT"
-  },
-  {
-    0x27, 0x05,
-    SenseDevTypes038,
-    "PERMANENT WRITE PROTECT"
-  },
-  {
-    0x28, 0x00,
-    SenseDevTypes001,
-    "NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED"
-  },
-  {
-    0x28, 0x01,
-    SenseDevTypes039,
-    "IMPORT OR EXPORT ELEMENT ACCESSED"
-  },
-  {
-    0x29, 0x00,
-    SenseDevTypes001,
-    "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
-  },
-  {
-    0x29, 0x01,
-    SenseDevTypes001,
-    "POWER ON OCCURRED"
-  },
-  {
-    0x29, 0x02,
-    SenseDevTypes001,
-    "SCSI BUS RESET OCCURRED"
-  },
-  {
-    0x29, 0x03,
-    SenseDevTypes001,
-    "BUS DEVICE RESET FUNCTION OCCURRED"
-  },
-  {
-    0x29, 0x04,
-    SenseDevTypes001,
-    "DEVICE INTERNAL RESET"
-  },
-  {
-    0x29, 0x05,
-    SenseDevTypes001,
-    "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED"
-  },
-  {
-    0x29, 0x06,
-    SenseDevTypes001,
-    "TRANSCEIVER MODE CHANGED TO LVD"
-  },
-  {
-    0x2A, 0x00,
-    SenseDevTypes013,
-    "PARAMETERS CHANGED"
-  },
-  {
-    0x2A, 0x01,
-    SenseDevTypes013,
-    "MODE PARAMETERS CHANGED"
-  },
-  {
-    0x2A, 0x02,
-    SenseDevTypes040,
-    "LOG PARAMETERS CHANGED"
-  },
-  {
-    0x2A, 0x03,
-    SenseDevTypes036,
-    "RESERVATIONS PREEMPTED"
-  },
-  {
-    0x2A, 0x04,
-    SenseDevTypes041,
-    "RESERVATIONS RELEASED"
-  },
-  {
-    0x2A, 0x05,
-    SenseDevTypes041,
-    "REGISTRATIONS PREEMPTED"
-  },
-  {
-    0x2B, 0x00,
-    SenseDevTypes016,
-    "COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT"
-  },
-  {
-    0x2C, 0x00,
-    SenseDevTypes001,
-    "COMMAND SEQUENCE ERROR"
-  },
-  {
-    0x2C, 0x01,
-    SenseDevTypes042,
-    "TOO MANY WINDOWS SPECIFIED"
-  },
-  {
-    0x2C, 0x02,
-    SenseDevTypes042,
-    "INVALID COMBINATION OF WINDOWS SPECIFIED"
-  },
-  {
-    0x2C, 0x03,
-    SenseDevTypes005,
-    "CURRENT PROGRAM AREA IS NOT EMPTY"
-  },
-  {
-    0x2C, 0x04,
-    SenseDevTypes005,
-    "CURRENT PROGRAM AREA IS EMPTY"
-  },
-  {
-    0x2C, 0x05,
-    SenseDevTypes043,
-    "ILLEGAL POWER CONDITION REQUEST"
-  },
-  {
-    0x2D, 0x00,
-    SenseDevTypes002,
-    "OVERWRITE ERROR ON UPDATE IN PLACE"
-  },
-  {
-    0x2E, 0x00,
-    SenseDevTypes044,
-    "ERROR DETECTED BY THIRD PARTY TEMPORARY INITIATOR"
-  },
-  {
-    0x2E, 0x01,
-    SenseDevTypes044,
-    "THIRD PARTY DEVICE FAILURE"
-  },
-  {
-    0x2E, 0x02,
-    SenseDevTypes044,
-    "COPY TARGET DEVICE NOT REACHABLE"
-  },
-  {
-    0x2E, 0x03,
-    SenseDevTypes044,
-    "INCORRECT COPY TARGET DEVICE TYPE"
-  },
-  {
-    0x2E, 0x04,
-    SenseDevTypes044,
-    "COPY TARGET DEVICE DATA UNDERRUN"
-  },
-  {
-    0x2E, 0x05,
-    SenseDevTypes044,
-    "COPY TARGET DEVICE DATA OVERRUN"
-  },
-  {
-    0x2F, 0x00,
-    SenseDevTypes001,
-    "COMMANDS CLEARED BY ANOTHER INITIATOR"
-  },
-  {
-    0x30, 0x00,
-    SenseDevTypes034,
-    "INCOMPATIBLE MEDIUM INSTALLED"
-  },
-  {
-    0x30, 0x01,
-    SenseDevTypes029,
-    "CANNOT READ MEDIUM - UNKNOWN FORMAT"
-  },
-  {
-    0x30, 0x02,
-    SenseDevTypes029,
-    "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT"
-  },
-  {
-    0x30, 0x03,
-    SenseDevTypes045,
-    "CLEANING CARTRIDGE INSTALLED"
-  },
-  {
-    0x30, 0x04,
-    SenseDevTypes029,
-    "CANNOT WRITE MEDIUM - UNKNOWN FORMAT"
-  },
-  {
-    0x30, 0x05,
-    SenseDevTypes029,
-    "CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT"
-  },
-  {
-    0x30, 0x06,
-    SenseDevTypes017,
-    "CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM"
-  },
-  {
-    0x30, 0x07,
-    SenseDevTypes006,
-    "CLEANING FAILURE"
-  },
-  {
-    0x30, 0x08,
-    SenseDevTypes005,
-    "CANNOT WRITE - APPLICATION CODE MISMATCH"
-  },
-  {
-    0x30, 0x09,
-    SenseDevTypes005,
-    "CURRENT SESSION NOT FIXATED FOR APPEND"
-  },
-  {
-    0x31, 0x00,
-    SenseDevTypes029,
-    "MEDIUM FORMAT CORRUPTED"
-  },
-  {
-    0x31, 0x01,
-    SenseDevTypes046,
-    "FORMAT COMMAND FAILED"
-  },
-  {
-    0x32, 0x00,
-    SenseDevTypes007,
-    "NO DEFECT SPARE LOCATION AVAILABLE"
-  },
-  {
-    0x32, 0x01,
-    SenseDevTypes007,
-    "DEFECT LIST UPDATE FAILURE"
-  },
-  {
-    0x33, 0x00,
-    SenseDevTypes002,
-    "TAPE LENGTH ERROR"
-  },
-  {
-    0x34, 0x00,
-    SenseDevTypes001,
-    "ENCLOSURE FAILURE"
-  },
-  {
-    0x35, 0x00,
-    SenseDevTypes001,
-    "ENCLOSURE SERVICES FAILURE"
-  },
-  {
-    0x35, 0x01,
-    SenseDevTypes001,
-    "UNSUPPORTED ENCLOSURE FUNCTION"
-  },
-  {
-    0x35, 0x02,
-    SenseDevTypes001,
-    "ENCLOSURE SERVICES UNAVAILABLE"
-  },
-  {
-    0x35, 0x03,
-    SenseDevTypes001,
-    "ENCLOSURE SERVICES TRANSFER FAILURE"
-  },
-  {
-    0x35, 0x04,
-    SenseDevTypes001,
-    "ENCLOSURE SERVICES TRANSFER REFUSED"
-  },
-  {
-    0x36, 0x00,
-    SenseDevTypes047,
-    "RIBBON, INK, OR TONER FAILURE"
-  },
-  {
-    0x37, 0x00,
-    SenseDevTypes013,
-    "ROUNDED PARAMETER"
-  },
-  {
-    0x38, 0x00,
-    SenseDevTypes043,
-    "EVENT STATUS NOTIFICATION"
-  },
-  {
-    0x38, 0x02,
-    SenseDevTypes043,
-    "ESN - POWER MANAGEMENT CLASS EVENT"
-  },
-  {
-    0x38, 0x04,
-    SenseDevTypes043,
-    "ESN - MEDIA CLASS EVENT"
-  },
-  {
-    0x38, 0x06,
-    SenseDevTypes043,
-    "ESN - DEVICE BUSY CLASS EVENT"
-  },
-  {
-    0x39, 0x00,
-    SenseDevTypes040,
-    "SAVING PARAMETERS NOT SUPPORTED"
-  },
-  {
-    0x3A, 0x00,
-    SenseDevTypes014,
-    "MEDIUM NOT PRESENT"
-  },
-  {
-    0x3A, 0x01,
-    SenseDevTypes034,
-    "MEDIUM NOT PRESENT - TRAY CLOSED"
-  },
-  {
-    0x3A, 0x02,
-    SenseDevTypes034,
-    "MEDIUM NOT PRESENT - TRAY OPEN"
-  },
-  {
-    0x3A, 0x03,
-    SenseDevTypes039,
-    "MEDIUM NOT PRESENT - LOADABLE"
-  },
-  {
-    0x3A, 0x04,
-    SenseDevTypes039,
-    "MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE"
-  },
-  {
-    0x3B, 0x00,
-    SenseDevTypes048,
-    "SEQUENTIAL POSITIONING ERROR"
-  },
-  {
-    0x3B, 0x01,
-    SenseDevTypes002,
-    "TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM"
-  },
-  {
-    0x3B, 0x02,
-    SenseDevTypes002,
-    "TAPE POSITION ERROR AT END-OF-MEDIUM"
-  },
-  {
-    0x3B, 0x03,
-    SenseDevTypes047,
-    "TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY"
-  },
-  {
-    0x3B, 0x04,
-    SenseDevTypes047,
-    "SLEW FAILURE"
-  },
-  {
-    0x3B, 0x05,
-    SenseDevTypes047,
-    "PAPER JAM"
-  },
-  {
-    0x3B, 0x06,
-    SenseDevTypes047,
-    "FAILED TO SENSE TOP-OF-FORM"
-  },
-  {
-    0x3B, 0x07,
-    SenseDevTypes047,
-    "FAILED TO SENSE BOTTOM-OF-FORM"
-  },
-  {
-    0x3B, 0x08,
-    SenseDevTypes002,
-    "REPOSITION ERROR"
-  },
-  {
-    0x3B, 0x09,
-    SenseDevTypes042,
-    "READ PAST END OF MEDIUM"
-  },
-  {
-    0x3B, 0x0A,
-    SenseDevTypes042,
-    "READ PAST BEGINNING OF MEDIUM"
-  },
-  {
-    0x3B, 0x0B,
-    SenseDevTypes042,
-    "POSITION PAST END OF MEDIUM"
-  },
-  {
-    0x3B, 0x0C,
-    SenseDevTypes003,
-    "POSITION PAST BEGINNING OF MEDIUM"
-  },
-  {
-    0x3B, 0x0D,
-    SenseDevTypes034,
-    "MEDIUM DESTINATION ELEMENT FULL"
-  },
-  {
-    0x3B, 0x0E,
-    SenseDevTypes034,
-    "MEDIUM SOURCE ELEMENT EMPTY"
-  },
-  {
-    0x3B, 0x0F,
-    SenseDevTypes005,
-    "END OF MEDIUM REACHED"
-  },
-  {
-    0x3B, 0x11,
-    SenseDevTypes034,
-    "MEDIUM MAGAZINE NOT ACCESSIBLE"
-  },
-  {
-    0x3B, 0x12,
-    SenseDevTypes034,
-    "MEDIUM MAGAZINE REMOVED"
-  },
-  {
-    0x3B, 0x13,
-    SenseDevTypes034,
-    "MEDIUM MAGAZINE INSERTED"
-  },
-  {
-    0x3B, 0x14,
-    SenseDevTypes034,
-    "MEDIUM MAGAZINE LOCKED"
-  },
-  {
-    0x3B, 0x15,
-    SenseDevTypes034,
-    "MEDIUM MAGAZINE UNLOCKED"
-  },
-  {
-    0x3B, 0x16,
-    SenseDevTypes005,
-    "MECHANICAL POSITIONING OR CHANGER ERROR"
-  },
-  {
-    0x3D, 0x00,
-    SenseDevTypes036,
-    "INVALID BITS IN IDENTIFY MESSAGE"
-  },
-  {
-    0x3E, 0x00,
-    SenseDevTypes001,
-    "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET"
-  },
-  {
-    0x3E, 0x01,
-    SenseDevTypes001,
-    "LOGICAL UNIT FAILURE"
-  },
-  {
-    0x3E, 0x02,
-    SenseDevTypes001,
-    "TIMEOUT ON LOGICAL UNIT"
-  },
-  {
-    0x3E, 0x03,
-    SenseDevTypes001,
-    "LOGICAL UNIT FAILED SELF-TEST"
-  },
-  {
-    0x3E, 0x04,
-    SenseDevTypes001,
-    "LOGICAL UNIT UNABLE TO UPDATE SELF-TEST LOG"
-  },
-  {
-    0x3F, 0x00,
-    SenseDevTypes001,
-    "TARGET OPERATING CONDITIONS HAVE CHANGED"
-  },
-  {
-    0x3F, 0x01,
-    SenseDevTypes001,
-    "MICROCODE HAS BEEN CHANGED"
-  },
-  {
-    0x3F, 0x02,
-    SenseDevTypes049,
-    "CHANGED OPERATING DEFINITION"
-  },
-  {
-    0x3F, 0x03,
-    SenseDevTypes001,
-    "INQUIRY DATA HAS CHANGED"
-  },
-  {
-    0x3F, 0x04,
-    SenseDevTypes050,
-    "COMPONENT DEVICE ATTACHED"
-  },
-  {
-    0x3F, 0x05,
-    SenseDevTypes050,
-    "DEVICE IDENTIFIER CHANGED"
-  },
-  {
-    0x3F, 0x06,
-    SenseDevTypes051,
-    "REDUNDANCY GROUP CREATED OR MODIFIED"
-  },
-  {
-    0x3F, 0x07,
-    SenseDevTypes051,
-    "REDUNDANCY GROUP DELETED"
-  },
-  {
-    0x3F, 0x08,
-    SenseDevTypes051,
-    "SPARE CREATED OR MODIFIED"
-  },
-  {
-    0x3F, 0x09,
-    SenseDevTypes051,
-    "SPARE DELETED"
-  },
-  {
-    0x3F, 0x0A,
-    SenseDevTypes050,
-    "VOLUME SET CREATED OR MODIFIED"
-  },
-  {
-    0x3F, 0x0B,
-    SenseDevTypes050,
-    "VOLUME SET DELETED"
-  },
-  {
-    0x3F, 0x0C,
-    SenseDevTypes050,
-    "VOLUME SET DEASSIGNED"
-  },
-  {
-    0x3F, 0x0D,
-    SenseDevTypes050,
-    "VOLUME SET REASSIGNED"
-  },
-  {
-    0x3F, 0x0E,
-    SenseDevTypes041,
-    "REPORTED LUNS DATA HAS CHANGED"
-  },
-  {
-    0x3F, 0x0F,
-    SenseDevTypes001,
-    "ECHO BUFFER OVERWRITTEN"
-  },
-  {
-    0x3F, 0x10,
-    SenseDevTypes039,
-    "MEDIUM LOADABLE"
-  },
-  {
-    0x3F, 0x11,
-    SenseDevTypes039,
-    "MEDIUM AUXILIARY MEMORY ACCESSIBLE"
-  },
-  {
-    0x40, 0x00,
-    SenseDevTypes035,
-    "RAM FAILURE (SHOULD USE 40 NN)"
-  },
-  {
-    0x40, 0xFF,
-    SenseDevTypes001,
-    "DIAGNOSTIC FAILURE ON COMPONENT NN (80H-FFH)"
-  },
-  {
-    0x41, 0x00,
-    SenseDevTypes035,
-    "DATA PATH FAILURE (SHOULD USE 40 NN)"
-  },
-  {
-    0x42, 0x00,
-    SenseDevTypes035,
-    "POWER-ON OR SELF-TEST FAILURE (SHOULD USE 40 NN)"
-  },
-  {
-    0x43, 0x00,
-    SenseDevTypes001,
-    "MESSAGE ERROR"
-  },
-  {
-    0x44, 0x00,
-    SenseDevTypes001,
-    "INTERNAL TARGET FAILURE"
-  },
-  {
-    0x45, 0x00,
-    SenseDevTypes001,
-    "SELECT OR RESELECT FAILURE"
-  },
-  {
-    0x46, 0x00,
-    SenseDevTypes049,
-    "UNSUCCESSFUL SOFT RESET"
-  },
-  {
-    0x47, 0x00,
-    SenseDevTypes001,
-    "SCSI PARITY ERROR"
-  },
-  {
-    0x47, 0x01,
-    SenseDevTypes001,
-    "DATA PHASE CRC ERROR DETECTED"
-  },
-  {
-    0x47, 0x02,
-    SenseDevTypes001,
-    "SCSI PARITY ERROR DETECTED DURING ST DATA PHASE"
-  },
-  {
-    0x47, 0x03,
-    SenseDevTypes001,
-    "INFORMATION UNIT CRC ERROR DETECTED"
-  },
-  {
-    0x47, 0x04,
-    SenseDevTypes001,
-    "ASYNCHRONOUS INFORMATION PROTECTION ERROR DETECTED"
-  },
-  {
-    0x48, 0x00,
-    SenseDevTypes001,
-    "INITIATOR DETECTED ERROR MESSAGE RECEIVED"
-  },
-  {
-    0x49, 0x00,
-    SenseDevTypes001,
-    "INVALID MESSAGE ERROR"
-  },
-  {
-    0x4A, 0x00,
-    SenseDevTypes001,
-    "COMMAND PHASE ERROR"
-  },
-  {
-    0x4B, 0x00,
-    SenseDevTypes001,
-    "DATA PHASE ERROR"
-  },
-  {
-    0x4C, 0x00,
-    SenseDevTypes001,
-    "LOGICAL UNIT FAILED SELF-CONFIGURATION"
-  },
-  {
-    0x4D, 0xFF,
-    SenseDevTypes001,
-    "TAGGED OVERLAPPED COMMANDS (NN = QUEUE TAG)"
-  },
-  {
-    0x4E, 0x00,
-    SenseDevTypes001,
-    "OVERLAPPED COMMANDS ATTEMPTED"
-  },
-  {
-    0x50, 0x00,
-    SenseDevTypes002,
-    "WRITE APPEND ERROR"
-  },
-  {
-    0x50, 0x01,
-    SenseDevTypes002,
-    "WRITE APPEND POSITION ERROR"
-  },
-  {
-    0x50, 0x02,
-    SenseDevTypes002,
-    "POSITION ERROR RELATED TO TIMING"
-  },
-  {
-    0x51, 0x00,
-    SenseDevTypes052,
-    "ERASE FAILURE"
-  },
-  {
-    0x52, 0x00,
-    SenseDevTypes002,
-    "CARTRIDGE FAULT"
-  },
-  {
-    0x53, 0x00,
-    SenseDevTypes014,
-    "MEDIA LOAD OR EJECT FAILED"
-  },
-  {
-    0x53, 0x01,
-    SenseDevTypes002,
-    "UNLOAD TAPE FAILURE"
-  },
-  {
-    0x53, 0x02,
-    SenseDevTypes034,
-    "MEDIUM REMOVAL PREVENTED"
-  },
-  {
-    0x54, 0x00,
-    SenseDevTypes053,
-    "SCSI TO HOST SYSTEM INTERFACE FAILURE"
-  },
-  {
-    0x55, 0x00,
-    SenseDevTypes053,
-    "SYSTEM RESOURCE FAILURE"
-  },
-  {
-    0x55, 0x01,
-    SenseDevTypes033,
-    "SYSTEM BUFFER FULL"
-  },
-  {
-    0x55, 0x02,
-    SenseDevTypes054,
-    "INSUFFICIENT RESERVATION RESOURCES"
-  },
-  {
-    0x55, 0x03,
-    SenseDevTypes041,
-    "INSUFFICIENT RESOURCES"
-  },
-  {
-    0x55, 0x04,
-    SenseDevTypes055,
-    "INSUFFICIENT REGISTRATION RESOURCES"
-  },
-  {
-    0x55, 0x05,
-    SenseDevTypes012,
-    "access controls code 4 (99-314) [proposed]"
-  },
-  {
-    0x55, 0x06,
-    SenseDevTypes012,
-    "auxiliary memory code 1 (99-148) [proposed]"
-  },
-  {
-    0x57, 0x00,
-    SenseDevTypes005,
-    "UNABLE TO RECOVER TABLE-OF-CONTENTS"
-  },
-  {
-    0x58, 0x00,
-    SenseDevTypes056,
-    "GENERATION DOES NOT EXIST"
-  },
-  {
-    0x59, 0x00,
-    SenseDevTypes056,
-    "UPDATED BLOCK READ"
-  },
-  {
-    0x5A, 0x00,
-    SenseDevTypes057,
-    "OPERATOR REQUEST OR STATE CHANGE INPUT"
-  },
-  {
-    0x5A, 0x01,
-    SenseDevTypes034,
-    "OPERATOR MEDIUM REMOVAL REQUEST"
-  },
-  {
-    0x5A, 0x02,
-    SenseDevTypes058,
-    "OPERATOR SELECTED WRITE PROTECT"
-  },
-  {
-    0x5A, 0x03,
-    SenseDevTypes058,
-    "OPERATOR SELECTED WRITE PERMIT"
-  },
-  {
-    0x5B, 0x00,
-    SenseDevTypes059,
-    "LOG EXCEPTION"
-  },
-  {
-    0x5B, 0x01,
-    SenseDevTypes059,
-    "THRESHOLD CONDITION MET"
-  },
-  {
-    0x5B, 0x02,
-    SenseDevTypes059,
-    "LOG COUNTER AT MAXIMUM"
-  },
-  {
-    0x5B, 0x03,
-    SenseDevTypes059,
-    "LOG LIST CODES EXHAUSTED"
-  },
-  {
-    0x5C, 0x00,
-    SenseDevTypes060,
-    "RPL STATUS CHANGE"
-  },
-  {
-    0x5C, 0x01,
-    SenseDevTypes060,
-    "SPINDLES SYNCHRONIZED"
-  },
-  {
-    0x5C, 0x02,
-    SenseDevTypes060,
-    "SPINDLES NOT SYNCHRONIZED"
-  },
-  {
-    0x5D, 0x00,
-    SenseDevTypes001,
-    "FAILURE PREDICTION THRESHOLD EXCEEDED"
-  },
-  {
-    0x5D, 0x01,
-    SenseDevTypes061,
-    "MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED"
-  },
-  {
-    0x5D, 0x02,
-    SenseDevTypes005,
-    "LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED"
-  },
-  {
-    0x5D, 0x10,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
-  },
-  {
-    0x5D, 0x11,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x12,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x13,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x14,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
-  },
-  {
-    0x5D, 0x15,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x16,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x17,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS"
-  },
-  {
-    0x5D, 0x18,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED"
-  },
-  {
-    0x5D, 0x19,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"
-  },
-  {
-    0x5D, 0x1A,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"
-  },
-  {
-    0x5D, 0x1B,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"
-  },
-  {
-    0x5D, 0x1C,
-    SenseDevTypes062,
-    "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
-  },
-  {
-    0x5D, 0x20,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
-  },
-  {
-    0x5D, 0x21,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x22,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x23,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x24,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
-  },
-  {
-    0x5D, 0x25,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x26,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x27,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS"
-  },
-  {
-    0x5D, 0x28,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED"
-  },
-  {
-    0x5D, 0x29,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE"
-  },
-  {
-    0x5D, 0x2A,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE"
-  },
-  {
-    0x5D, 0x2B,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT"
-  },
-  {
-    0x5D, 0x2C,
-    SenseDevTypes062,
-    "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
-  },
-  {
-    0x5D, 0x30,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
-  },
-  {
-    0x5D, 0x31,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x32,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x33,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x34,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
-  },
-  {
-    0x5D, 0x35,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x36,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x37,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS"
-  },
-  {
-    0x5D, 0x38,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED"
-  },
-  {
-    0x5D, 0x39,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE"
-  },
-  {
-    0x5D, 0x3A,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE"
-  },
-  {
-    0x5D, 0x3B,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT"
-  },
-  {
-    0x5D, 0x3C,
-    SenseDevTypes062,
-    "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
-  },
-  {
-    0x5D, 0x40,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
-  },
-  {
-    0x5D, 0x41,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x42,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x43,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x44,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
-  },
-  {
-    0x5D, 0x45,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x46,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x47,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS"
-  },
-  {
-    0x5D, 0x48,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE CONTROLLER DETECTED"
-  },
-  {
-    0x5D, 0x49,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE"
-  },
-  {
-    0x5D, 0x4A,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE"
-  },
-  {
-    0x5D, 0x4B,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT"
-  },
-  {
-    0x5D, 0x4C,
-    SenseDevTypes062,
-    "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
-  },
-  {
-    0x5D, 0x50,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
-  },
-  {
-    0x5D, 0x51,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x52,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x53,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x54,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
-  },
-  {
-    0x5D, 0x55,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x56,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x57,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS"
-  },
-  {
-    0x5D, 0x58,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE CONTROLLER DETECTED"
-  },
-  {
-    0x5D, 0x59,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE"
-  },
-  {
-    0x5D, 0x5A,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE"
-  },
-  {
-    0x5D, 0x5B,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT"
-  },
-  {
-    0x5D, 0x5C,
-    SenseDevTypes062,
-    "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
-  },
-  {
-    0x5D, 0x60,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"
-  },
-  {
-    0x5D, 0x61,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x62,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x63,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"
-  },
-  {
-    0x5D, 0x64,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"
-  },
-  {
-    0x5D, 0x65,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x66,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"
-  },
-  {
-    0x5D, 0x67,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS"
-  },
-  {
-    0x5D, 0x68,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED"
-  },
-  {
-    0x5D, 0x69,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"
-  },
-  {
-    0x5D, 0x6A,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"
-  },
-  {
-    0x5D, 0x6B,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"
-  },
-  {
-    0x5D, 0x6C,
-    SenseDevTypes062,
-    "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"
-  },
-  {
-    0x5D, 0xFF,
-    SenseDevTypes001,
-    "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)"
-  },
-  {
-    0x5E, 0x00,
-    SenseDevTypes044,
-    "LOW POWER CONDITION ON"
-  },
-  {
-    0x5E, 0x01,
-    SenseDevTypes044,
-    "IDLE CONDITION ACTIVATED BY TIMER"
-  },
-  {
-    0x5E, 0x02,
-    SenseDevTypes044,
-    "STANDBY CONDITION ACTIVATED BY TIMER"
-  },
-  {
-    0x5E, 0x03,
-    SenseDevTypes044,
-    "IDLE CONDITION ACTIVATED BY COMMAND"
-  },
-  {
-    0x5E, 0x04,
-    SenseDevTypes044,
-    "STANDBY CONDITION ACTIVATED BY COMMAND"
-  },
-  {
-    0x5E, 0x41,
-    SenseDevTypes043,
-    "POWER STATE CHANGE TO ACTIVE"
-  },
-  {
-    0x5E, 0x42,
-    SenseDevTypes043,
-    "POWER STATE CHANGE TO IDLE"
-  },
-  {
-    0x5E, 0x43,
-    SenseDevTypes043,
-    "POWER STATE CHANGE TO STANDBY"
-  },
-  {
-    0x5E, 0x45,
-    SenseDevTypes043,
-    "POWER STATE CHANGE TO SLEEP"
-  },
-  {
-    0x5E, 0x47,
-    SenseDevTypes063,
-    "POWER STATE CHANGE TO DEVICE CONTROL"
-  },
-  {
-    0x60, 0x00,
-    SenseDevTypes042,
-    "LAMP FAILURE"
-  },
-  {
-    0x61, 0x00,
-    SenseDevTypes042,
-    "VIDEO ACQUISITION ERROR"
-  },
-  {
-    0x61, 0x01,
-    SenseDevTypes042,
-    "UNABLE TO ACQUIRE VIDEO"
-  },
-  {
-    0x61, 0x02,
-    SenseDevTypes042,
-    "OUT OF FOCUS"
-  },
-  {
-    0x62, 0x00,
-    SenseDevTypes042,
-    "SCAN HEAD POSITIONING ERROR"
-  },
-  {
-    0x63, 0x00,
-    SenseDevTypes005,
-    "END OF USER AREA ENCOUNTERED ON THIS TRACK"
-  },
-  {
-    0x63, 0x01,
-    SenseDevTypes005,
-    "PACKET DOES NOT FIT IN AVAILABLE SPACE"
-  },
-  {
-    0x64, 0x00,
-    SenseDevTypes005,
-    "ILLEGAL MODE FOR THIS TRACK"
-  },
-  {
-    0x64, 0x01,
-    SenseDevTypes005,
-    "INVALID PACKET SIZE"
-  },
-  {
-    0x65, 0x00,
-    SenseDevTypes001,
-    "VOLTAGE FAULT"
-  },
-  {
-    0x66, 0x00,
-    SenseDevTypes042,
-    "AUTOMATIC DOCUMENT FEEDER COVER UP"
-  },
-  {
-    0x66, 0x01,
-    SenseDevTypes042,
-    "AUTOMATIC DOCUMENT FEEDER LIFT UP"
-  },
-  {
-    0x66, 0x02,
-    SenseDevTypes042,
-    "DOCUMENT JAM IN AUTOMATIC DOCUMENT FEEDER"
-  },
-  {
-    0x66, 0x03,
-    SenseDevTypes042,
-    "DOCUMENT MISS FEED AUTOMATIC IN DOCUMENT FEEDER"
-  },
-  {
-    0x67, 0x00,
-    SenseDevTypes064,
-    "CONFIGURATION FAILURE"
-  },
-  {
-    0x67, 0x01,
-    SenseDevTypes064,
-    "CONFIGURATION OF INCAPABLE LOGICAL UNITS FAILED"
-  },
-  {
-    0x67, 0x02,
-    SenseDevTypes064,
-    "ADD LOGICAL UNIT FAILED"
-  },
-  {
-    0x67, 0x03,
-    SenseDevTypes064,
-    "MODIFICATION OF LOGICAL UNIT FAILED"
-  },
-  {
-    0x67, 0x04,
-    SenseDevTypes064,
-    "EXCHANGE OF LOGICAL UNIT FAILED"
-  },
-  {
-    0x67, 0x05,
-    SenseDevTypes064,
-    "REMOVE OF LOGICAL UNIT FAILED"
-  },
-  {
-    0x67, 0x06,
-    SenseDevTypes064,
-    "ATTACHMENT OF LOGICAL UNIT FAILED"
-  },
-  {
-    0x67, 0x07,
-    SenseDevTypes064,
-    "CREATION OF LOGICAL UNIT FAILED"
-  },
-  {
-    0x67, 0x08,
-    SenseDevTypes064,
-    "ASSIGN FAILURE OCCURRED"
-  },
-  {
-    0x67, 0x09,
-    SenseDevTypes064,
-    "MULTIPLY ASSIGNED LOGICAL UNIT"
-  },
-  {
-    0x68, 0x00,
-    SenseDevTypes064,
-    "LOGICAL UNIT NOT CONFIGURED"
-  },
-  {
-    0x69, 0x00,
-    SenseDevTypes064,
-    "DATA LOSS ON LOGICAL UNIT"
-  },
-  {
-    0x69, 0x01,
-    SenseDevTypes064,
-    "MULTIPLE LOGICAL UNIT FAILURES"
-  },
-  {
-    0x69, 0x02,
-    SenseDevTypes064,
-    "PARITY/DATA MISMATCH"
-  },
-  {
-    0x6A, 0x00,
-    SenseDevTypes064,
-    "INFORMATIONAL, REFER TO LOG"
-  },
-  {
-    0x6B, 0x00,
-    SenseDevTypes064,
-    "STATE CHANGE HAS OCCURRED"
-  },
-  {
-    0x6B, 0x01,
-    SenseDevTypes064,
-    "REDUNDANCY LEVEL GOT BETTER"
-  },
-  {
-    0x6B, 0x02,
-    SenseDevTypes064,
-    "REDUNDANCY LEVEL GOT WORSE"
-  },
-  {
-    0x6C, 0x00,
-    SenseDevTypes064,
-    "REBUILD FAILURE OCCURRED"
-  },
-  {
-    0x6D, 0x00,
-    SenseDevTypes064,
-    "RECALCULATE FAILURE OCCURRED"
-  },
-  {
-    0x6E, 0x00,
-    SenseDevTypes064,
-    "COMMAND TO LOGICAL UNIT FAILED"
-  },
-  {
-    0x6F, 0x00,
-    SenseDevTypes005,
-    "COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE"
-  },
-  {
-    0x6F, 0x01,
-    SenseDevTypes005,
-    "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT"
-  },
-  {
-    0x6F, 0x02,
-    SenseDevTypes005,
-    "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED"
-  },
-  {
-    0x6F, 0x03,
-    SenseDevTypes005,
-    "READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION"
-  },
-  {
-    0x6F, 0x04,
-    SenseDevTypes005,
-    "MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION"
-  },
-  {
-    0x6F, 0x05,
-    SenseDevTypes005,
-    "DRIVE REGION MUST BE PERMANENT/REGION RESET COUNT ERROR"
-  },
-  {
-    0x70, 0xFF,
-    SenseDevTypes002,
-    "DECOMPRESSION EXCEPTION SHORT ALGORITHM ID OF NN"
-  },
-  {
-    0x71, 0x00,
-    SenseDevTypes002,
-    "DECOMPRESSION EXCEPTION LONG ALGORITHM ID"
-  },
-  {
-    0x72, 0x00,
-    SenseDevTypes005,
-    "SESSION FIXATION ERROR"
-  },
-  {
-    0x72, 0x01,
-    SenseDevTypes005,
-    "SESSION FIXATION ERROR WRITING LEAD-IN"
-  },
-  {
-    0x72, 0x02,
-    SenseDevTypes005,
-    "SESSION FIXATION ERROR WRITING LEAD-OUT"
-  },
-  {
-    0x72, 0x03,
-    SenseDevTypes005,
-    "SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION"
-  },
-  {
-    0x72, 0x04,
-    SenseDevTypes005,
-    "EMPTY OR PARTIALLY WRITTEN RESERVED TRACK"
-  },
-  {
-    0x72, 0x05,
-    SenseDevTypes005,
-    "NO MORE TRACK RESERVATIONS ALLOWED"
-  },
-  {
-    0x73, 0x00,
-    SenseDevTypes005,
-    "CD CONTROL ERROR"
-  },
-  {
-    0x73, 0x01,
-    SenseDevTypes005,
-    "POWER CALIBRATION AREA ALMOST FULL"
-  },
-  {
-    0x73, 0x02,
-    SenseDevTypes005,
-    "POWER CALIBRATION AREA IS FULL"
-  },
-  {
-    0x73, 0x03,
-    SenseDevTypes005,
-    "POWER CALIBRATION AREA ERROR"
-  },
-  {
-    0x73, 0x04,
-    SenseDevTypes005,
-    "PROGRAM MEMORY AREA UPDATE FAILURE"
-  },
-  {
-    0x73, 0x05,
-    SenseDevTypes005,
-    "PROGRAM MEMORY AREA IS FULL"
-  },
-  {
-    0x73, 0x06,
-    SenseDevTypes005,
-    "RMA/PMA IS FULL"
-  },
-};
-
-static int ASCQ_TableSize = 463;
-
-
-#endif
diff -Nru a/drivers/message/fusion/ascq_tbl.sh b/drivers/message/fusion/ascq_tbl.sh
--- a/drivers/message/fusion/ascq_tbl.sh	2002-02-05 11:10:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,109 +0,0 @@
-#!/bin/sh
-#
-#  ascq_tbl.sh - Translate SCSI t10.org's "asc-num.txt" file of
-#                SCSI Additional Sense Code & Qualifiers (ASC/ASCQ's)
-#                into something useful in C, creating "ascq_tbl.c" file.
-#
-#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
-
-PREF_INFILE="t10.org/asc-num.txt"	# From SCSI t10.org
-PREF_OUTFILE="ascq_tbl.c"
-
-#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
-
-xlate_ascq() {
-	cat | awk '
-	BEGIN {
-		DQ = "\042";
-		OUTFILE = "'"${PREF_OUTFILE}"'";
-		TRUE = 1;
-		FALSE = 0;
-		#debug = TRUE;
-
-		#  read and discard all lines up to and including the one that begins
-		#  with the "magic token" of "-------  --------------  ---"...
-		headers_gone = FALSE;
-		while (!headers_gone) {
-			if (getline <= 0)
-				exit 1;
-			header_line[++hdrs] = $0;
-			if (debug)
-				printf("header_line[%d] = :%s:\n", ++hdrs, $0);
-			if ($0 ~ /^-------  --------------  ---/) {
-				headers_gone = TRUE;
-			}
-		}
-		outcount = 0;
-	}
-
-	(NF > 1) {
-		++outcount;
-		if (debug)
-			printf( "DBG: %s\n", $0 );
-		ASC[outcount] = substr($0,1,2);
-		ASCQ[outcount] = substr($0,5,2);
-		devtypes = substr($0,10,14);
-		gsub(/ /, ".", devtypes);
-		DESCRIP[outcount] = substr($0,26);
-
-		if (!(devtypes in DevTypesVoodoo)) {
-			DevTypesVoodoo[devtypes] = ++voodoo;
-			DevTypesIdx[voodoo] = devtypes;
-		}
-		DEVTYPES[outcount] = DevTypesVoodoo[devtypes];
-
-		#  Handle 0xNN exception stuff...
-		if (ASCQ[outcount] == "NN" || ASCQ[outcount] == "nn")
-			ASCQ[outcount] = "FF";
-	}
-
-	END {
-		printf("#ifndef SCSI_ASCQ_TBL_C_INCLUDED\n") > OUTFILE;
-		printf("#define SCSI_ASCQ_TBL_C_INCLUDED\n") >> OUTFILE;
-
-		printf("\n/* AuToMaGiCaLlY generated from: %s'"${FIN}"'%s\n", DQ, DQ) >> OUTFILE;
-		printf(" *******************************************************************************\n") >> OUTFILE;
-		for (i=1; i<=hdrs; i++) {
-			printf(" * %s\n", header_line[i]) >> OUTFILE;
-		}
-		printf(" */\n") >> OUTFILE;
-
-		printf("\n") >> OUTFILE;
-		for (i=1; i<=voodoo; i++) {
-			printf("static char SenseDevTypes%03d[] = %s%s%s;\n", i, DQ, DevTypesIdx[i], DQ) >> OUTFILE;
-		}
-
-		printf("\nstatic ASCQ_Table_t ASCQ_Table[] = {\n") >> OUTFILE;
-		for (i=1; i<=outcount; i++) {
-			printf("  {\n") >> OUTFILE; 
-			printf("    0x%s, 0x%s,\n", ASC[i], ASCQ[i]) >> OUTFILE;
-			printf("    SenseDevTypes%03d,\n", DEVTYPES[i]) >> OUTFILE;
-			printf("    %s%s%s\n", DQ, DESCRIP[i], DQ) >> OUTFILE;
-			printf("  },\n") >> OUTFILE;
-		}
-		printf( "};\n\n" ) >> OUTFILE;
-
-		printf( "static int ASCQ_TableSize = %d;\n\n", outcount ) >> OUTFILE;
-		printf( "Total of %d ASC/ASCQ records generated\n", outcount );
-		printf("\n#endif\n") >> OUTFILE;
-		close(OUTFILE);
-	}'
-	return
-}
-
-#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
-
-# main()
-if [ $# -lt 1 ]; then
-	echo "INFO: No input filename supplied - using: $PREF_INFILE" >&2
-	FIN=$PREF_INFILE
-else
-	FIN="$1"
-	if [ "$FIN" != "$PREF_INFILE" ]; then
-		echo "INFO: Ok, I'll try chewing on '$FIN' for SCSI ASC/ASCQ combos..." >&2
-	fi
-	shift
-fi
-
-cat $FIN | xlate_ascq
-exit 0
diff -Nru a/drivers/message/fusion/isense.c b/drivers/message/fusion/isense.c
--- a/drivers/message/fusion/isense.c	2004-05-29 08:10:51 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,119 +0,0 @@
-/*
- *  linux/drivers/message/fusion/isense.c
- *      Little linux driver / shim that interfaces with the Fusion MPT
- *      Linux base driver to provide english readable strings in SCSI
- *      Error Report logging output.  This module implements SCSI-3
- *      Opcode lookup and a sorted table of SCSI-3 ASC/ASCQ strings.
- *
- *  Copyright (c) 1991-2004 Steven J. Ralston
- *  Written By: Steven J. Ralston
- *  (yes I wrote some of the orig. code back in 1991!)
- *  (mailto:sjralston1@netscape.net)
- *  (mailto:mpt_linux_developer@lsil.com)
- *
- *  $Id: isense.c,v 1.33 2002/02/27 18:44:19 sralston Exp $
- */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
-    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; version 2 of the License.
-
-    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.
-
-    NO WARRANTY
-    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
-    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
-    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
-    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
-    solely responsible for determining the appropriateness of using and
-    distributing the Program and assumes all risks associated with its
-    exercise of rights under this Agreement, including but not limited to
-    the risks and costs of program errors, damage to or loss of data,
-    programs or equipment, and unavailability or interruption of operations.
-
-    DISCLAIMER OF LIABILITY
-    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
-    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
-    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-    USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
-    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <asm/io.h>
-
-#define MODULEAUTHOR "Steven J. Ralston"
-#define COPYRIGHT "Copyright (c) 2001-2004 " MODULEAUTHOR
-#include "mptbase.h"
-
-#include "isense.h"
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Private data...
- */
-
-/*
- *  YIKES!  I don't usually #include C source files, but..
- *  The following #include's pulls in our needed ASCQ_Table[] array,
- *  ASCQ_TableSz integer, and ScsiOpcodeString[] array!
- */
-#include "ascq_tbl.c"
-#include "scsiops.c"
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#define my_NAME		"SCSI-3 Opcodes & ASC/ASCQ Strings"
-#define my_VERSION	MPT_LINUX_VERSION_COMMON
-#define MYNAM		"isense"
-
-MODULE_AUTHOR(MODULEAUTHOR);
-MODULE_DESCRIPTION(my_NAME);
-MODULE_LICENSE("GPL");
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-int __init isense_init(void)
-{
-	show_mptmod_ver(my_NAME, my_VERSION);
-
-	/*
-	 *  Install our handler
-	 */
-	if (mpt_register_ascqops_strings(&ASCQ_Table[0], ASCQ_TableSize, ScsiOpcodeString) != 1)
-	{
-		printk(KERN_ERR MYNAM ": ERROR: Can't register with Fusion MPT base driver!\n");
-		return -EBUSY;
-	}
-	printk(KERN_INFO MYNAM ": Registered SCSI-3 Opcodes & ASC/ASCQ Strings\n");
-	return 0;
-}
-
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static void isense_exit(void)
-{
-#ifdef MODULE
-	mpt_deregister_ascqops_strings();
-#endif
-	printk(KERN_INFO MYNAM ": Deregistered SCSI-3 Opcodes & ASC/ASCQ Strings\n");
-}
-
-module_init(isense_init);
-module_exit(isense_exit);
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
diff -Nru a/drivers/message/fusion/isense.h b/drivers/message/fusion/isense.h
--- a/drivers/message/fusion/isense.h	2002-02-05 11:10:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,95 +0,0 @@
-#ifndef ISENSE_H_INCLUDED
-#define ISENSE_H_INCLUDED
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-#ifdef __KERNEL__
-#include <linux/types.h>		/* needed for u8, etc. */
-#include <linux/string.h>		/* needed for strcat   */
-#include <linux/kernel.h>		/* needed for sprintf  */
-#else
-    #ifndef U_STUFF_DEFINED
-    #define U_STUFF_DEFINED
-    typedef unsigned char u8;
-    typedef unsigned short u16;
-    typedef unsigned int u32;
-    #endif
-#endif
-
-#include "scsi3.h"			/* needed for all things SCSI */
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Defines and typedefs...
- */
-
-#ifdef __KERNEL__
-#define PrintF(x) printk x
-#else
-#define PrintF(x) printf x
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-#define RETRY_STATUS  ((int) 1)
-#define PUT_STATUS    ((int) 0)
-
-/*
- *    A generic structure to hold info about IO request that caused
- *    a Request Sense to be performed, and the resulting Sense Data.
- */
-typedef struct IO_Info
-{
-    char *DevIDStr;   /* String of chars which identifies the device.       */
-    u8   *cdbPtr;     /* Pointer (Virtual/Logical addr) to CDB bytes of
-                           IO request that caused ContAllegianceCond.       */
-    u8   *sensePtr;   /* Pointer (Virtual/Logical addr) to Sense Data
-                           returned by Request Sense operation.             */
-    u8   *dataPtr;    /* Pointer (Virtual/Logical addr) to Data buffer
-                           of IO request caused ContAllegianceCondition.    */
-    u8   *inqPtr;     /* Pointer (Virtual/Logical addr) to Inquiry Data for
-                           IO *Device* that caused ContAllegianceCondition. */
-    u8    SCSIStatus; /* SCSI status byte of IO request that caused
-                           Contingent Allegiance Condition.                 */
-    u8    DoDisplay;  /* Shall we display any messages?                     */
-    u16   rsvd_align1;
-    u32   ComplCode;  /* Four-byte OS-dependent completion code.            */
-    u32   NotifyL;    /* Four-byte OS-dependent notification field.         */
-} IO_Info_t;
-
-/*
- *  SCSI Additional Sense Code and Additional Sense Code Qualifier table.
- */
-typedef struct ASCQ_Table
-{
-    u8     ASC;
-    u8     ASCQ;
-    char  *DevTypes;
-    char  *Description;
-} ASCQ_Table_t;
-
-#if 0
-/*
- *  SCSI Opcodes table.
- */
-typedef struct SCSI_OPS_Table
-{
-    u8     OpCode;
-    char  *DevTypes;
-    char  *ScsiCmndStr;
-} SCSI_OPS_Table_t;
-#endif
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Public entry point prototypes
- */
-
-/* in scsiherr.c, needed by mptscsih.c */
-extern int	 mpt_ScsiHost_ErrorReport(IO_Info_t *ioop);
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-#endif
-
diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
--- a/drivers/message/fusion/mptbase.c	2004-06-26 19:26:07 -07:00
+++ b/drivers/message/fusion/mptbase.c	2004-08-27 08:36:38 -07:00
@@ -139,11 +139,6 @@
 
 DmpServices_t *DmpService;
 
-void *mpt_v_ASCQ_TablePtr;
-const char **mpt_ScsiOpcodesPtr;
-int mpt_ASCQ_TableSz;
-
-
 #define WHOINIT_UNKNOWN		0xAA
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -165,7 +160,6 @@
 static int	FusionInitCalled = 0;
 static int	mpt_base_index = -1;
 static int	last_drv_idx = -1;
-static int	isense_idx = -1;
 
 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
 
@@ -177,8 +171,8 @@
 static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
 
 static int	mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
-static void	mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
-static void	mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
+static void	mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
+static void	mpt_adapter_disable(MPT_ADAPTER *ioc);
 static void	mpt_adapter_dispose(MPT_ADAPTER *ioc);
 
 static void	MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
@@ -291,7 +285,7 @@
 	int		 type;
 	int		 freeme;
 
-	ioc = bus_id;
+	ioc = (MPT_ADAPTER *)bus_id;
 
 	/*
 	 *  Drain the reply FIFO!
@@ -333,8 +327,8 @@
 			cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
 			mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 
-			dprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n",
-					ioc->name, mr));
+			dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n",
+					ioc->name, mr, req_idx));
 			DBG_DUMP_REPLY_FRAME(mr)
 
 			/* NEW!  20010301 -sralston
@@ -358,7 +352,7 @@
 			/*
 			 *  Process turbo (context) reply...
 			 */
-			dirqprintk((MYIOC_s_INFO_FMT "Got TURBO reply(=%08x)\n", ioc->name, pa));
+			dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa));
 			type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
 			if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
 				cb_idx = mpt_stm_index;
@@ -506,7 +500,7 @@
 		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
 		if (results != evHandlers) {
 			/* CHECKME! Any special handling needed here? */
-			dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
+			devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
 					ioc->name, evHandlers, results));
 		}
 
@@ -659,8 +653,6 @@
 		MptEvHandlers[cb_idx] = NULL;
 
 		last_drv_idx++;
-		if (isense_idx != -1 && isense_idx <= cb_idx)
-			isense_idx++;
 	}
 }
 
@@ -803,56 +795,60 @@
  *	mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
  *	allocated per MPT adapter.
  *	@handle: Handle of registered MPT protocol driver
- *	@iocid: IOC unique identifier (integer)
+ *	@ioc: Pointer to MPT adapter structure
  *
  *	Returns pointer to a MPT request frame or %NULL if none are available
  *	or IOC is not active.
  */
 MPT_FRAME_HDR*
-mpt_get_msg_frame(int handle, MPT_ADAPTER *iocp)
+mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
 {
 	MPT_FRAME_HDR *mf;
 	unsigned long flags;
+	u16	 req_idx;	/* Request index */
+
+	/* validate handle and ioc identifier */
 
 #ifdef MFCNT
-	if (!iocp->active)
+	if (!ioc->active)
 		printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
 #endif
 
 	/* If interrupts are not attached, do not return a request frame */
-	if (!iocp->active)
+	if (!ioc->active)
 		return NULL;
 
-	spin_lock_irqsave(&iocp->FreeQlock, flags);
-	if (! Q_IS_EMPTY(&iocp->FreeQ)) {
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	if (! Q_IS_EMPTY(&ioc->FreeQ)) {
 		int req_offset;
 
-		mf = iocp->FreeQ.head;
+		mf = ioc->FreeQ.head;
 		Q_DEL_ITEM(&mf->u.frame.linkage);
 		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;	/* byte */
-		req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
+		req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 								/* u16! */
-		mf->u.frame.hwhdr.msgctxu.fld.req_idx =
-				cpu_to_le16(req_offset / iocp->req_sz);
+		req_idx = cpu_to_le16(req_offset / ioc->req_sz);
+		mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
 		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+		ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
 #ifdef MFCNT
-		iocp->mfcnt++;
+		ioc->mfcnt++;
 #endif
 	}
 	else
 		mf = NULL;
-	spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 #ifdef MFCNT
 	if (mf == NULL)
-		printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", iocp->mfcnt, iocp->req_depth);
+		printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
 	mfcounter++;
 	if (mfcounter == PRINT_MF_COUNT)
-		printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth);
+		printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
 #endif
 
 	dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
-			iocp->name, handle, iocid, mf));
+			ioc->name, handle, ioc->id, mf));
 	return mf;
 }
 
@@ -861,23 +857,25 @@
  *	mpt_put_msg_frame - Send a protocol specific MPT request frame
  *	to a IOC.
  *	@handle: Handle of registered MPT protocol driver
- *	@iocid: IOC unique identifier (integer)
+ *	@ioc: Pointer to MPT adapter structure
  *	@mf: Pointer to MPT request frame
  *
  *	This routine posts a MPT request frame to the request post FIFO of a
  *	specific MPT adapter.
  */
 void
-mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf)
+mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 {
 	u32 mf_dma_addr;
 	int req_offset;
+	u16	 req_idx;	/* Request index */
 
 	/* ensure values are reset properly! */
 	mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;		/* byte */
-	req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
-									/* u16! */
-	mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
+	req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
+								/* u16! */
+	req_idx = cpu_to_le16(req_offset / ioc->req_sz);
+	mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
 	mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 
 #ifdef MPT_DEBUG_MSG_FRAME
@@ -886,8 +884,8 @@
 		int	 ii, n;
 
 		printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
-				iocp->name, m);
-		n = iocp->req_sz/4 - 1;
+				ioc->name, m);
+		n = ioc->req_sz/4 - 1;
 		while (m[n] == 0)
 			n--;
 		for (ii=0; ii<=n; ii++) {
@@ -899,32 +897,33 @@
 	}
 #endif
 
-	mf_dma_addr = iocp->req_frames_low_dma + req_offset;
-	CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
+	mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];  
+	dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
+	CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mpt_free_msg_frame - Place MPT request frame back on FreeQ.
  *	@handle: Handle of registered MPT protocol driver
- *	@iocid: IOC unique identifier (integer)
+ *	@ioc: Pointer to MPT adapter structure
  *	@mf: Pointer to MPT request frame
  *
  *	This routine places a MPT request frame back on the MPT adapter's
  *	FreeQ.
  */
 void
-mpt_free_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf)
+mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 {
 	unsigned long flags;
 
 	/*  Put Request back on FreeQ!  */
-	spin_lock_irqsave(&iocp->FreeQlock, flags);
-	Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
 #ifdef MFCNT
-	iocp->mfcnt--;
+	ioc->mfcnt--;
 #endif
-	spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -996,7 +995,7 @@
  *	mpt_send_handshake_request - Send MPT request via doorbell
  *	handshake method.
  *	@handle: Handle of registered MPT protocol driver
- *	@iocid: IOC unique identifier (integer)
+ *	@ioc: Pointer to MPT adapter structure
  *	@reqBytes: Size of the request in bytes
  *	@req: Pointer to MPT request frame
  *	@sleepFlag: Use schedule if CAN_SLEEP else use udelay.
@@ -1010,7 +1009,7 @@
  *	Returns 0 for success, non-zero for failure.
  */
 int
-mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req, int sleepFlag)
+mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
 {
 	int		 r = 0;
 	u8	*req_as_bytes;
@@ -1026,37 +1025,38 @@
 	 * setting cb_idx/req_idx.  But ONLY if this request
 	 * is in proper (pre-alloc'd) request buffer range...
 	 */
-	ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
-	if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) {
+	ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
+	if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
 		MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
 		mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
 		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
 	}
 
 	/* Make sure there are no doorbells */
-	CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
-	CHIPREG_WRITE32(&iocp->chip->Doorbell,
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	
+	CHIPREG_WRITE32(&ioc->chip->Doorbell,
 			((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
 			 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
 
 	/* Wait for IOC doorbell int */
-	ii = WaitForDoorbellInt(iocp, 5, sleepFlag);
-	if (ii < 0)
+	if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
 		return ii;
+	}
 
 	/* Read doorbell and check for active bit */
-	if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
+	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
 		return -5;
 
 	dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
-			iocp->name, ii));
+			ioc->name, ii));
 
-	CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
-	r = WaitForDoorbellAck(iocp, 5, sleepFlag);
-	if (r < 0)
+	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
 		return -2;
-
+	}
+		
 	/* Send request via doorbell handshake */
 	req_as_bytes = (u8 *) req;
 	for (ii = 0; ii < reqBytes/4; ii++) {
@@ -1066,21 +1066,21 @@
 			(req_as_bytes[(ii*4) + 1] <<  8) |
 			(req_as_bytes[(ii*4) + 2] << 16) |
 			(req_as_bytes[(ii*4) + 3] << 24));
-		CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
-		r = WaitForDoorbellAck(iocp, 5, sleepFlag);
-		if (r < 0) {
+		CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
+		if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
 			r = -3;
 			break;
 		}
 	}
 
-	if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0)
+	if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
 		r = 0;
 	else
 		r = -4;
 
 	/* Make sure there are no doorbells */
-	CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	
 	return r;
 }
 
@@ -1141,11 +1141,15 @@
 	u8		 revision;
 	u8		 pcixcmd;
 	static int	 mpt_ids = 0;
+#ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *dent, *ent;
+#endif
 
 	if (pci_enable_device(pdev))
 		return r;
 	
+	dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
+	
 	if (!pci_set_dma_mask(pdev, mask)) {
 		dprintk((KERN_INFO MYNAM
 			": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
@@ -1170,9 +1174,8 @@
 	ioc->alloc_total = sizeof(MPT_ADAPTER);
 	ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;		/* avoid div by zero! */
 	ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
-
+	
 	ioc->pcidev = pdev;
-
 	ioc->diagPending = 0;
 	spin_lock_init(&ioc->diagLock);
 
@@ -1223,8 +1226,8 @@
 		return -EINVAL;
 	}
 
-	dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
-	dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
+	dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
+	dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
 
 	mem = NULL;
 	/* Get logical ptr for PciMem0 space */
@@ -1236,15 +1239,15 @@
 		return -EINVAL;
 	}
 	ioc->memmap = mem;
-	dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
+	dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
 
-	dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
+	dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
 			&ioc->facts, &ioc->pfacts[0]));
 
 	ioc->mem_phys = mem_phys;
 	ioc->chip = (SYSIF_REGS*)mem;
 
-	/* Save Port IO values incase we need to do downloadboot */
+	/* Save Port IO values in case we need to do downloadboot */
 	{
 		u8 *pmem = (u8*)port;
 		ioc->pio_mem_phys = port;
@@ -1314,7 +1317,6 @@
 
 	sprintf(ioc->name, "ioc%d", ioc->id);
 
-	Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
 	spin_lock_init(&ioc->FreeQlock);
 
 	/* Disable all! */
@@ -1337,7 +1339,6 @@
 			printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
 					ioc->name, __irq_itoa(pdev->irq));
 #endif
-			Q_DEL_ITEM(ioc);
 			list_del(&ioc->list);
 			iounmap(mem);
 			kfree(ioc);
@@ -1369,7 +1370,6 @@
 		  ": WARNING - %s did not initialize properly! (%d)\n",
 		  ioc->name, r);
 
-		Q_DEL_ITEM(ioc);
 		list_del(&ioc->list);
 		free_irq(ioc->pci_irq, ioc);
 		iounmap(mem);
@@ -1386,6 +1386,7 @@
 		}
 	}
 
+#ifdef CONFIG_PROC_FS
 	/*
 	 *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
 	 */
@@ -1402,6 +1403,7 @@
 			ent->data = ioc;
 		}
 	}
+#endif
 
 	return 0;
 }
@@ -1625,7 +1627,7 @@
 	int	 hard_reset_done = 0;
 	int	 alt_ioc_ready = 0;
 	int	 hard;
-	int	 r;
+	int	 rc=0;
 	int	 ii;
 	int	 handlers;
 	int	 ret = 0;
@@ -1675,39 +1677,37 @@
 	 * and 1 if a hard reset was performed.
 	 */
 	if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
-		if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
+		if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
 			alt_ioc_ready = 1;
 		else
 			printk(KERN_WARNING MYNAM
-					": alt-%s: (%d) Not ready WARNING!\n",
-					ioc->alt_ioc->name, r);
+					": alt-%s: Not ready WARNING!\n",
+					ioc->alt_ioc->name);
 	}
 
 	for (ii=0; ii<5; ii++) {
-		/* Get IOC facts! Allow 1 retry */
-		if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) {
-			dinitprintk((MYIOC_s_INFO_FMT 
-			     "ii=%d IocFacts failed r=%x\n", ioc->name, ii, r));
-		} else
+		/* Get IOC facts! Allow 5 retries */
+		if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
 			break;
 	}
+	
 
-	if (r) {
-		dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed r=%x\n", ioc->name, r));
+	if (ii == 5) {
+		dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
 		ret = -2;
 	} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 		MptDisplayIocCapabilities(ioc);
 	}
-
+	
 	if (alt_ioc_ready) {
-		if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
-			dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed r=%x\n", ioc->name, r));
+		if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
+			dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
 			/* Retry - alt IOC was initialized once
 			 */
-			r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
+			rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
 		}
-		if (r) {
-			dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed r=%x\n", ioc->name, r));
+		if (rc) {
+			dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
 			alt_ioc_ready = 0;
 			reset_alt_ioc_active = 0;
 		} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
@@ -1720,29 +1720,29 @@
 	 * init as upper addresses are needed for init.
 	 * If fails, continue with alt-ioc processing
 	 */
-	if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0))
+	if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
 		ret = -3;
 
 	/* May need to check/upload firmware & data here!
 	 * If fails, continue with alt-ioc processing
 	 */
-	if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0))
+	if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
 		ret = -4;
 // NEW!
-	if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
+	if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
 		printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
-				ioc->alt_ioc->name, r);
+				ioc->alt_ioc->name, rc);
 		alt_ioc_ready = 0;
 		reset_alt_ioc_active = 0;
 	}
 
 	if (alt_ioc_ready) {
-		if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
+		if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
 			alt_ioc_ready = 0;
 			reset_alt_ioc_active = 0;
 			printk(KERN_WARNING MYNAM
 				": alt-%s: (%d) init failure WARNING!\n",
-					ioc->alt_ioc->name, r);
+					ioc->alt_ioc->name, rc);
 		}
 	}
 
@@ -1754,18 +1754,8 @@
 			/* Controller is not operational, cannot do upload
 			 */
 			if (ret == 0) {
-				r = mpt_do_upload(ioc, sleepFlag);
-				if (r != 0)
-					printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
-			}
-
-			/* Handle the alt IOC too */
-			if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){
-				ddlprintk((MYIOC_s_INFO_FMT
-					"Alt-ioc firmware upload required!\n",
-					ioc->name));
-				r = mpt_do_upload(ioc->alt_ioc, sleepFlag);
-				if (r != 0)
+				rc = mpt_do_upload(ioc, sleepFlag);
+				if (rc != 0)
 					printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
 			}
 		}
@@ -1859,19 +1849,19 @@
 	 * MptResetHandlers[] registered yet.
 	 */
 	if (hard_reset_done) {
-		r = handlers = 0;
+		rc = handlers = 0;
 		for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
 			if ((ret == 0) && MptResetHandlers[ii]) {
 				dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
 						ioc->name, ii));
-				r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+				rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
 				handlers++;
 			}
 
 			if (alt_ioc_ready && MptResetHandlers[ii]) {
 				dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
 						ioc->name, ioc->alt_ioc->name, ii));
-				r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
+				rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
 				handlers++;
 			}
 		}
@@ -1932,84 +1922,90 @@
 /*
  *	mpt_adapter_disable - Disable misbehaving MPT adapter.
  *	@this: Pointer to MPT adapter structure
- *	@free: Free up alloc'd reply, request, etc.
  */
 static void
-mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
+mpt_adapter_disable(MPT_ADAPTER *ioc)
 {
-	if (this != NULL) {
-		int sz=0;
-		int ret;
-
-		if (this->cached_fw != NULL) {
-			ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n"));
+	int sz;
+	int ret;
 
-			if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) {
-				printk(KERN_WARNING MYNAM
-					": firmware downloadboot failure (%d)!\n", ret);
-			}
+	if (ioc->cached_fw != NULL) {
+		ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
+		if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) {
+			printk(KERN_WARNING MYNAM
+				": firmware downloadboot failure (%d)!\n", ret);
 		}
+	}
 
-		/* Disable adapter interrupts! */
-		CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
-		this->active = 0;
-		/* Clear any lingering interrupt */
-		CHIPREG_WRITE32(&this->chip->IntStatus, 0);
-
-		if (freeup && this->fifo_pool != NULL) {
-			pci_free_consistent(this->pcidev,
-				this->fifo_pool_sz,
-				this->fifo_pool, this->fifo_pool_dma);
-			this->reply_frames = NULL;
-			this->reply_alloc = NULL;
-			this->req_frames = NULL;
-			this->req_alloc = NULL;
-			this->chain_alloc = NULL;
-			this->fifo_pool = NULL;
-			this->alloc_total -= this->fifo_pool_sz;
-		}
-		if (freeup && this->sense_buf_pool != NULL) {
-			sz = (this->req_depth * MPT_SENSE_BUFFER_ALLOC);
-			pci_free_consistent(this->pcidev, sz,
-					this->sense_buf_pool, this->sense_buf_pool_dma);
-			this->sense_buf_pool = NULL;
-			this->alloc_total -= sz;
-		}
-
-		if (freeup && this->events != NULL){
-			sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
-			kfree(this->events);
-			this->events = NULL;
-			this->alloc_total -= sz;
-		}
-
-		if (freeup && this->cached_fw != NULL) {
-
-			sz = this->facts.FWImageSize;
-			pci_free_consistent(this->pcidev, sz,
-				this->cached_fw, this->cached_fw_dma);
-			this->cached_fw = NULL;
-			this->alloc_total -= sz;
-		}
-
-		if (freeup && this->spi_data.nvram != NULL) {
-			kfree(this->spi_data.nvram);
-			this->spi_data.nvram = NULL;
-		}
-
-		if (freeup && this->spi_data.pIocPg3 != NULL) {
-			kfree(this->spi_data.pIocPg3);
-			this->spi_data.pIocPg3 = NULL;
-		}
-
-		if (freeup && this->spi_data.pIocPg4 != NULL) {
-			sz = this->spi_data.IocPg4Sz;
-			pci_free_consistent(this->pcidev, sz,
-				this->spi_data.pIocPg4,
-				this->spi_data.IocPg4_dma);
-			this->spi_data.pIocPg4 = NULL;
-			this->alloc_total -= sz;
-		}
+	/* Disable adapter interrupts! */
+	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+	ioc->active = 0;
+	/* Clear any lingering interrupt */
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+	if (ioc->alloc != NULL) {
+		sz = ioc->alloc_sz;
+		dexitprintk((KERN_INFO MYNAM ": %s.free  @ %p, sz=%d bytes\n",
+		 	ioc->name, ioc->alloc, ioc->alloc_sz));
+		pci_free_consistent(ioc->pcidev, sz,
+				ioc->alloc, ioc->alloc_dma);
+		ioc->reply_frames = NULL;
+		ioc->req_frames = NULL;
+		ioc->alloc = NULL;
+		ioc->alloc_total -= sz;
+	}
+
+	if (ioc->sense_buf_pool != NULL) {
+		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
+		pci_free_consistent(ioc->pcidev, sz,
+				ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+		ioc->sense_buf_pool = NULL;
+		ioc->alloc_total -= sz;
+	}
+
+	if (ioc->events != NULL){
+		sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
+		kfree(ioc->events);
+		ioc->events = NULL;
+		ioc->alloc_total -= sz;
+	}
+
+	if (ioc->cached_fw != NULL) {
+		sz = ioc->facts.FWImageSize;
+		pci_free_consistent(ioc->pcidev, sz,
+			ioc->cached_fw, ioc->cached_fw_dma);
+		ioc->cached_fw = NULL;
+		ioc->alloc_total -= sz;
+	}
+
+	if (ioc->spi_data.nvram != NULL) {
+		kfree(ioc->spi_data.nvram);
+		ioc->spi_data.nvram = NULL;
+	}
+
+	if (ioc->spi_data.pIocPg3 != NULL) {
+		kfree(ioc->spi_data.pIocPg3);
+		ioc->spi_data.pIocPg3 = NULL;
+	}
+
+	if (ioc->spi_data.pIocPg4 != NULL) {
+		sz = ioc->spi_data.IocPg4Sz;
+		pci_free_consistent(ioc->pcidev, sz, 
+			ioc->spi_data.pIocPg4,
+			ioc->spi_data.IocPg4_dma);
+		ioc->spi_data.pIocPg4 = NULL;
+		ioc->alloc_total -= sz;
+	}
+
+	if (ioc->ReqToChain != NULL) {
+		kfree(ioc->ReqToChain);
+		kfree(ioc->RequestNB);
+		ioc->ReqToChain = NULL;
+	}
+
+	if (ioc->ChainToChain != NULL) {
+		kfree(ioc->ChainToChain);
+		ioc->ChainToChain = NULL;
 	}
 }
 
@@ -2017,43 +2013,43 @@
 /*
  *	mpt_adapter_dispose - Free all resources associated with a MPT
  *	adapter.
- *	@this: Pointer to MPT adapter structure
+ *	@ioc: Pointer to MPT adapter structure
  *
  *	This routine unregisters h/w resources and frees all alloc'd memory
  *	associated with a MPT adapter structure.
  */
 static void
-mpt_adapter_dispose(MPT_ADAPTER *this)
+mpt_adapter_dispose(MPT_ADAPTER *ioc)
 {
-	if (this != NULL) {
+	if (ioc != NULL) {
 		int sz_first, sz_last;
 
-		sz_first = this->alloc_total;
+		sz_first = ioc->alloc_total;
 
-		mpt_adapter_disable(this, 1);
+		mpt_adapter_disable(ioc);
 
-		if (this->pci_irq != -1) {
-			free_irq(this->pci_irq, this);
-			this->pci_irq = -1;
+		if (ioc->pci_irq != -1) {
+			free_irq(ioc->pci_irq, ioc);
+			ioc->pci_irq = -1;
 		}
 
-		if (this->memmap != NULL)
-			iounmap((u8 *) this->memmap);
+		if (ioc->memmap != NULL)
+			iounmap((u8 *) ioc->memmap);
 
 #if defined(CONFIG_MTRR) && 0
-		if (this->mtrr_reg > 0) {
-			mtrr_del(this->mtrr_reg, 0, 0);
-			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
+		if (ioc->mtrr_reg > 0) {
+			mtrr_del(ioc->mtrr_reg, 0, 0);
+			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
 		}
 #endif
 
 		/*  Zap the adapter lookup ptr!  */
-		list_del(&this->list);
+		list_del(&ioc->list);
 
-		sz_last = this->alloc_total;
+		sz_last = ioc->alloc_total;
 		dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
-				this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
-		kfree(this);
+				ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+		kfree(ioc);
 	}
 }
 
@@ -2228,13 +2224,13 @@
 		ii++; cntdn--;
 		if (!cntdn) {
 			printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
-					ioc->name, (ii+5)/HZ);
+					ioc->name, (int)((ii+5)/HZ));
 			return -ETIME;
 		}
 
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 		} else {
 			mdelay (1);	/* 1 msec delay */
 		}
@@ -2292,7 +2288,9 @@
 	int			 r;
 	int			 req_sz;
 	int			 reply_sz;
-	u32			 status;
+	int			 sz;
+	u32			 status, vv;
+	u8			 shiftFactor=1;
 
 	/* IOC *must* NOT be in RESET state! */
 	if (ioc->last_state == MPI_IOC_STATE_RESET) {
@@ -2315,7 +2313,9 @@
 	get_facts.Function = MPI_FUNCTION_IOC_FACTS;
 	/* Assert: All other get_facts fields are zero! */
 
-	dinitprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
+	dinitprintk((MYIOC_s_INFO_FMT 
+	    "Sending get IocFacts request req_sz=%d reply_sz=%d\n", 
+	    ioc->name, req_sz, reply_sz));
 
 	/* No non-zero fields in the get_facts request are greater than
 	 * 1 byte in size, so we can just fire it off as is.
@@ -2388,6 +2388,13 @@
 			facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
 		}
 
+		sz = facts->FWImageSize;
+		if ( sz & 0x01 )
+			sz += 1;
+		if ( sz & 0x02 )
+			sz += 2;
+		facts->FWImageSize = sz;
+		
 		if (!facts->RequestFrameSize) {
 			/*  Something is wrong!  */
 			printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
@@ -2395,6 +2402,18 @@
 			return -55;
 		}
 
+		r = sz = le32_to_cpu(facts->BlockSize);
+		vv = ((63 / (sz * 4)) + 1) & 0x03;
+		ioc->NB_for_64_byte_frame = vv;
+		while ( sz )
+		{
+			shiftFactor++;
+			sz = sz >> 1;
+		}
+		ioc->NBShiftFactor  = shiftFactor;
+		dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
+					ioc->name, vv, shiftFactor, r));
+    
 		if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 			/*
 			 * Set values for this IOC's request & reply frame sizes,
@@ -2405,9 +2424,9 @@
 			ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
 			ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
 
-			dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
+			dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
 				ioc->name, ioc->reply_sz, ioc->reply_depth));
-			dprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
+			dinitprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
 				ioc->name, ioc->req_sz, ioc->req_depth));
 
 			/* Get port facts! */
@@ -2416,7 +2435,7 @@
 		}
 	} else {
 		printk(MYIOC_s_ERR_FMT 
-		     "Invalid IOC facts reply, msgLength=%d offsetof=%d!\n",
+		     "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
 		     ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
 		     RequestFrameSize)/sizeof(u32)));
 		return -66;
@@ -2465,7 +2484,7 @@
 	get_pfacts.PortNumber = portnum;
 	/* Assert: All other get_pfacts fields are zero! */
 
-	dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
+	dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
 			ioc->name, portnum));
 
 	/* No non-zero fields in the get_pfacts request are greater than
@@ -2516,24 +2535,18 @@
 	memset(&init_reply, 0, sizeof(init_reply));
 
 	ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
-/*	ioc_init.ChainOffset = 0;			*/
 	ioc_init.Function = MPI_FUNCTION_IOC_INIT;
-/*	ioc_init.Flags = 0;				*/
 
 	/* If we are in a recovery mode and we uploaded the FW image,
 	 * then this pointer is not NULL. Skip the upload a second time.
 	 * Set this flag if cached_fw set for either IOC.
 	 */
-	ioc->upload_fw = 0;
-	ioc_init.Flags = 0;
-	if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
-		if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw))
-			ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE;
-		else
-			ioc->upload_fw = 1;
-	}
-	ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n",
-		   ioc->name, ioc_init.Flags, ioc->upload_fw));
+	if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
+		ioc->upload_fw = 1;
+	else
+		ioc->upload_fw = 0;
+	ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
+		   ioc->name, ioc->upload_fw, ioc->facts.Flags));
 
 	if ((int)ioc->chip_type <= (int)FC929) {
 		ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
@@ -2542,17 +2555,13 @@
 	}
 	ioc_init.MaxBuses = MPT_MAX_BUS;
 
-/*	ioc_init.MsgFlags = 0;				*/
-/*	ioc_init.MsgContext = cpu_to_le32(0x00000000);	*/
 	ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);	/* in BYTES */
-		
-	ioc->facts.RequestFrameSize = ioc_init.ReplyFrameSize;
 
 	if (sizeof(dma_addr_t) == sizeof(u64)) {
 		/* Save the upper 32-bits of the request
 		 * (reply) and sense buffers.
 		 */
-		ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
+		ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
 		ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
 	} else {
 		/* Force 32-bit addressing */
@@ -2591,14 +2600,14 @@
 	while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 		} else {
 			mdelay(1);
 		}
 
 		if (!cntdn) {
 			printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
-					ioc->name, (count+5)/HZ);
+					ioc->name, (int)((count+5)/HZ));
 			return -9;
 		}
 
@@ -2644,7 +2653,7 @@
 /*	port_enable.MsgFlags = 0;		*/
 /*	port_enable.MsgContext = 0;		*/
 
-	dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
+	dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
 			ioc->name, portnum, &port_enable));
 
 	/* RAID FW may take a long time to enable
@@ -2668,20 +2677,22 @@
 }
 
 /*
- * Inputs: size - total FW bytes
- * Outputs: frags - number of fragments needed
- * Return NULL if failed.
+ *	ioc: Pointer to MPT_ADAPTER structure
+ *      size - total FW bytes
  */
 void
 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
 {
-	/* cached_fw
-	 */
-
-	if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
-		ioc->alloc_total += size;
+	if (ioc->cached_fw)
+		return;  /* use already allocated memory */
+	if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
+		ioc->cached_fw = ioc->alt_ioc->cached_fw;  /* use alt_ioc's memory */
+		ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
+	} else {
+		if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
+			ioc->alloc_total += size;
+	}
 }
-
 /*
  * If alt_img is NULL, delete from ioc structure.
  * Else, delete a secondary image in same format.
@@ -2692,6 +2703,8 @@
 	int sz;
 
 	sz = ioc->facts.FWImageSize;
+	dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
 	pci_free_consistent(ioc->pcidev, sz,
 			ioc->cached_fw, ioc->cached_fw_dma);
 	ioc->cached_fw = NULL;
@@ -2725,30 +2738,24 @@
 	int			 sgeoffset;
 	u32			 flagsLength;
 	int			 ii, sz, reply_sz;
-	int			 cmdStatus, freeMem = 0;
+	int			 cmdStatus;
 
-	/* If the image size is 0 or if the pointer is
-	 * not NULL (error), we are done.
+	/* If the image size is 0, we are done.
 	 */
-	if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw)
+	if ((sz = ioc->facts.FWImageSize) == 0)
 		return 0;
 
-	if ( sz & 0x01 )
-		sz += 1;
-	if ( sz & 0x02 )
-		sz += 2;
-
 	mpt_alloc_fw_memory(ioc, sz);
 
+	dinitprintk((KERN_WARNING MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
+	
 	if (ioc->cached_fw == NULL) {
 		/* Major Failure.
 		 */
 		return -ENOMEM;
 	}
 
-	dinitprintk((KERN_WARNING MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
-		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
-
 	prequest = (FWUpload_t *)&request;
 	preply = (FWUploadReply_t *)&reply;
 
@@ -2797,23 +2804,11 @@
 	dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
 			ioc->name, cmdStatus));
 
-	/* Check to see if we have a copy of this image in
-	 * host memory already.
-	 */
-	if (cmdStatus == 0) {
-		ioc->upload_fw = 0;
-		if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
-			freeMem = 1;
-	}
-
-	/* We already have a copy of this image or
-	 * we had some type of an error  - either the handshake
-	 * failed (i != 0) or the command did not complete successfully.
-	 */
-	if (cmdStatus || freeMem) {
+	
+	if (cmdStatus) {
 
-		ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n",
-			ioc->name, cmdStatus ? "incomplete" : "duplicate"));
+		ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
+			ioc->name));
 		mpt_free_fw_memory(ioc);
 	}
 
@@ -2841,28 +2836,26 @@
 	MpiExtImageHeader_t	*pExtImage;
 	u32			 fwSize;
 	u32			 diag0val;
-#ifdef MPT_DEBUG
-	u32			 diag1val = 0;
-#endif
-	int			 count = 0;
+	int			 count;
 	u32			*ptrFw;
 	u32			 diagRwData;
 	u32			 nextImage;
 	u32			 load_addr;
-	u32 			 ioc_state;
+	u32 			 ioc_state=0;
 
 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n",
 				ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
 
-	/* Get dma_addr and data transfer size.
-	 */
 	if ( ioc->facts.FWImageSize == 0 )
 		return -1;
 
-	/* Get the DMA from ioc or ioc->alt_ioc */
 	if (ioc->cached_fw == NULL)
 		return -2;
 
+	/* prevent a second downloadboot and memory free with alt_ioc */
+	if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
+		ioc->alt_ioc->cached_fw = NULL;
+	
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
@@ -2870,18 +2863,17 @@
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
 
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	diag0val |= (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
 
-	/* wait 100 msec */
+	/* wait 1 msec */
 	if (sleepFlag == CAN_SLEEP) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(100 * HZ / 1000);
+		schedule_timeout(1 * HZ / 1000);
 	} else {
-		mdelay (100);
+		mdelay (1);
 	}
 
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
 	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
 
 	for (count = 0; count < 30; count ++) {
@@ -2894,7 +2886,7 @@
 		/* wait 1 sec */
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ);
+			schedule_timeout(1000 * HZ / 1000);
 		} else {
 			mdelay (1000);
 		}
@@ -2914,8 +2906,7 @@
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
 
 	/* Set the DiagRwEn and Disable ARM bits */
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (diag0val | MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
 
 	pFwHeader = (MpiFwHeader_t *) ioc->cached_fw;
 	fwSize = (pFwHeader->ImageSize + 3)/4;
@@ -2961,15 +2952,6 @@
 	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
 
-	/* clear the PREVENT_IOC_BOOT bit */
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT\n",
-		ioc->name, diag0val));
-	diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT);
-	ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
-		ioc->name, diag0val));
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
-
 	/* Clear the internal flash bad bit - autoincrementing register,
 	 * so must do two writes.
 	 */
@@ -2980,28 +2962,13 @@
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
 
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off DISABLE_ARM, RW_ENABLE, RESET_HISTORY\n",
+	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
 		ioc->name, diag0val));
-	diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_RESET_HISTORY);
+	diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
 		ioc->name, diag0val));
 	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
 
-	/* wait 100 msec */
-	if (sleepFlag == CAN_SLEEP) {
-		ddlprintk((MYIOC_s_INFO_FMT "CAN_SLEEP 100 msec before reset the sequencer\n", ioc->name));
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(100 * HZ / 1000);
-	} else {
-		ddlprintk((MYIOC_s_INFO_FMT "mdelay 100 msec before reset the sequencer\n", ioc->name));
-		mdelay (100);
-	}
-
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	if ( diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_DISABLE_ARM) ) {
-		ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed, diag0val=%x FLASH_BAD_SIG | DISABLE_ARM on\n ",
-			ioc->name, diag0val));
-	}
 	/* Write 0xFF to reset the sequencer */
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 
@@ -3009,26 +2976,18 @@
 		if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
 			ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
 					ioc->name, count, ioc_state));
-/*			if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
-				if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
-					ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed\n",
-						ioc->name));
-						return -EFAULT;
-				}
-			} */
-			/* wait 2 sec */
-/*			if (sleepFlag == CAN_SLEEP) {
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(5000 * HZ / 1000);
-			} else {
-				mdelay (5000);
-			} */
-
+			if ((SendIocInit(ioc, sleepFlag)) != 0) {
+				ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
+					ioc->name));
+				return -EFAULT;
+			}
+			ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
+					ioc->name));
 			return 0;
 		}
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(10 * HZ / 1000);
 		} else {
 			mdelay (10);
 		}
@@ -3068,8 +3027,8 @@
 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 {
 	int hard_reset_done = 0;
-	u32 ioc_state;
-	int cntdn, cnt = 0;
+	u32 ioc_state=0;
+	int cnt,cntdn;
 
 	dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
 	if ((int)ioc->chip_type > (int)FC929) {
@@ -3080,7 +3039,7 @@
 
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ);
+			schedule_timeout(1000 * HZ / 1000);
 		} else {
 			mdelay (1000);
 		}
@@ -3090,26 +3049,27 @@
 	if (hard_reset_done < 0)
 		return hard_reset_done;
 
-	dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
+	dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
 			ioc->name));
 
-	cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 20;	/* 20 seconds */
+	cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;	/* 2 seconds */
 	for (cnt=0; cnt<cntdn; cnt++) {
-		if ((ioc_state = mpt_GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
-			dprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
-					ioc->name, cnt));
+		ioc_state = mpt_GetIocState(ioc, 1);
+		if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
+			dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
+ 					ioc->name, cnt));
 			return hard_reset_done;
 		}
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(10 * HZ / 1000);
 		} else {
 			mdelay (10);
 		}
 	}
 
-	printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n",
-			ioc->name);
+	printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
+			ioc->name, ioc_state);
 	return -1;
 }
 
@@ -3199,12 +3159,6 @@
 		dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
 				ioc->name, diag0val, diag1val));
 #endif
-		/* Write the PreventIocBoot bit */
-		if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
-			diag0val |= MPI_DIAG_PREVENT_IOC_BOOT;
-			CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
-		}
-
 		/*
 		 * Disable the ARM (Bug fix)
 		 *
@@ -3246,20 +3200,13 @@
 			/* FIXME?  Examine results here? */
 		}
 
-		if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
+		if (ioc->cached_fw) {
 			/* If the DownloadBoot operation fails, the
 			 * IOC will be left unusable. This is a fatal error
 			 * case.  _diag_reset will return < 0
 			 */
 			for (count = 0; count < 30; count ++) {
 				diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-#ifdef MPT_DEBUG
-				if (ioc->alt_ioc)
-					diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
-				dprintk((MYIOC_s_INFO_FMT
-					"DbG2b: diag0=%08x, diag1=%08x\n",
-					ioc->name, diag0val, diag1val));
-#endif
 				if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
 					break;
 				}
@@ -3267,7 +3214,7 @@
 				/* wait 1 sec */
 				if (sleepFlag == CAN_SLEEP) {
 					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ);
+					schedule_timeout(1000 * HZ / 1000);
 				} else {
 					mdelay (1000);
 				}
@@ -3295,7 +3242,7 @@
 				/* wait 1 sec */
 				if (sleepFlag == CAN_SLEEP) {
 					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ);
+					schedule_timeout(1000 * HZ / 1000);
 				} else {
 					mdelay (1000);
 				}
@@ -3419,13 +3366,13 @@
 				count *= 10;
 
 			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
-					ioc->name, (count+5)/HZ);
+					ioc->name, (int)((count+5)/HZ));
 			return -ETIME;
 		}
 
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 		} else {
 			mdelay (1);	/* 1 msec delay */
 		}
@@ -3443,35 +3390,45 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	PrimeIocFifos - Initialize IOC request and reply FIFOs.
- *	@ioc: Pointer to MPT_ADAPTER structure
- *
- *	This routine allocates memory for the MPT reply and request frame
- *	pools (if necessary), and primes the IOC reply FIFO with
- *	reply frames.
- *
- *	Returns 0 for success, non-zero for failure.
+ *	initChainBuffers - Allocate memory for and initialize
+ *	chain buffers, chain buffer control arrays and spinlock.
+ *	@hd: Pointer to MPT_SCSI_HOST structure
+ *	@init: If set, initialize the spin lock.
  */
 static int
-PrimeIocFifos(MPT_ADAPTER *ioc)
+initChainBuffers(MPT_ADAPTER *ioc)
 {
-	MPT_FRAME_HDR *mf;
-	unsigned long b;
-	unsigned long flags;
-	dma_addr_t aligned_mem_dma;
-	u8 *aligned_mem;
-	int i, sz;
-	int chain_buffer_sz, reply_buffer_sz, request_buffer_sz;
-	int scale, num_sge, num_chain;
-
-	/* request buffer size,  rounding UP to nearest 4-kB boundary */
-	request_buffer_sz = (ioc->req_sz * ioc->req_depth) + 128;
-	request_buffer_sz = ((request_buffer_sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+	u8		*mem;
+	int		sz, ii, num_chain;
+	int 		scale, num_sge, numSGE;
+
+	/* ReqToChain size must equal the req_depth
+	 * index = req_idx
+	 */
+	if (ioc->ReqToChain == NULL) {
+		sz = ioc->req_depth * sizeof(int);
+		mem = kmalloc(sz, GFP_ATOMIC);
+		if (mem == NULL)
+			return -1;
+
+		ioc->ReqToChain = (int *) mem;
+		dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc  @ %p, sz=%d bytes\n",
+			 	ioc->name, mem, sz));
+		mem = kmalloc(sz, GFP_ATOMIC);
+		if (mem == NULL)
+			return -1;
 
-	/* reply buffer size */
-	reply_buffer_sz = (ioc->reply_sz * ioc->reply_depth) + 128;
+		ioc->RequestNB = (int *) mem;
+		dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc  @ %p, sz=%d bytes\n",
+			 	ioc->name, mem, sz));
+	}
+	for (ii = 0; ii < ioc->req_depth; ii++) {
+		ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
+	}
 
-	/* chain buffer size, copied from from mptscsih_initChainBuffers()
+	/* ChainToChain size must equal the total number
+	 * of chain buffers to be allocated.
+	 * index = chain_idx
 	 *
 	 * Calculate the number of chain buffers needed(plus 1) per I/O
 	 * then multiply the the maximum number of simultaneous cmds
@@ -3479,79 +3436,134 @@
 	 * num_sge = num sge in request frame + last chain buffer
 	 * scale = num sge per chain buffer if no chain element
 	 */
-
 	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
 	if (sizeof(dma_addr_t) == sizeof(u64))
 		num_sge =  scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
 	else
-		num_sge =  1 + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+		num_sge =  1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+
+	if (sizeof(dma_addr_t) == sizeof(u64)) {
+		numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+			(ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
+	} else {
+		numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+			(ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+	}
+	dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
+		ioc->name, num_sge, numSGE));
+
+	if ( numSGE > MPT_SCSI_SG_DEPTH	)
+		numSGE = MPT_SCSI_SG_DEPTH;
 
 	num_chain = 1;
-	while (MPT_SCSI_SG_DEPTH - num_sge > 0) {
+	while (numSGE - num_sge > 0) {
 		num_chain++;
 		num_sge += (scale - 1);
 	}
 	num_chain++;
 
-	if ((int)ioc->chip_type > (int) FC929)
+	dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
+		ioc->name, numSGE, num_sge, num_chain));
+
+	if ((int) ioc->chip_type > (int) FC929)
 		num_chain *= MPT_SCSI_CAN_QUEUE;
 	else
 		num_chain *= MPT_FC_CAN_QUEUE;
 
-	chain_buffer_sz = num_chain * ioc->req_sz;
+	ioc->num_chain = num_chain;
 
-	if(ioc->fifo_pool == NULL) {
+	sz = num_chain * sizeof(int);
+	if (ioc->ChainToChain == NULL) {
+		mem = kmalloc(sz, GFP_ATOMIC);
+		if (mem == NULL)
+			return -1;
 
-		ioc->fifo_pool_sz = request_buffer_sz +
-			reply_buffer_sz + chain_buffer_sz;
+		ioc->ChainToChain = (int *) mem;
+		dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
+			 	ioc->name, mem, sz));
+	} else {
+		mem = (u8 *) ioc->ChainToChain;
+	}
+	memset(mem, 0xFF, sz);
+	return num_chain;
+}
 
-		ioc->fifo_pool = pci_alloc_consistent(ioc->pcidev,
-		ioc->fifo_pool_sz, &ioc->fifo_pool_dma);
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	PrimeIocFifos - Initialize IOC request and reply FIFOs.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	This routine allocates memory for the MPT reply and request frame
+ *	pools (if necessary), and primes the IOC reply FIFO with
+ *	reply frames.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+PrimeIocFifos(MPT_ADAPTER *ioc)
+{
+	MPT_FRAME_HDR *mf;
+	unsigned long flags;
+	dma_addr_t alloc_dma;
+	u8 *mem;
+	int i, reply_sz, sz, total_size, num_chain;
 
-		if( ioc->fifo_pool == NULL)
+	/*  Prime reply FIFO...  */
+
+	if (ioc->reply_frames == NULL) {
+		if ( (num_chain = initChainBuffers(ioc)) < 0)
+			return -1;
+
+		total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
+		dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
+			 	ioc->name, ioc->reply_sz, ioc->reply_depth));
+		dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
+			 	ioc->name, reply_sz, reply_sz));
+
+		sz = (ioc->req_sz * ioc->req_depth);
+		dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
+			 	ioc->name, ioc->req_sz, ioc->req_depth));
+		dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
+			 	ioc->name, sz, sz));
+		total_size += sz;
+
+		sz = num_chain * ioc->req_sz; /* chain buffer pool size */
+		dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
+			 	ioc->name, ioc->req_sz, num_chain));
+		dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
+			 	ioc->name, sz, sz, num_chain));
+
+		total_size += sz;
+		mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
+		if (mem == NULL) {
+			printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
+				ioc->name);
 			goto out_fail;
+		}
 
-		ioc->alloc_total += ioc->fifo_pool_sz;
-		memset(ioc->fifo_pool, 0, ioc->fifo_pool_sz);
+		dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
+			 	ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
 
-		/* reply fifo pointers */
-		ioc->reply_alloc = ioc->fifo_pool;
-		ioc->reply_alloc_dma = ioc->fifo_pool_dma;
-		/* request fifo pointers */
-		ioc->req_alloc = ioc->reply_alloc+reply_buffer_sz;
-		ioc->req_alloc_dma = ioc->reply_alloc_dma+reply_buffer_sz;
-		/* chain buffer pointers */
-		ioc->chain_alloc = ioc->req_alloc+request_buffer_sz;
-		ioc->chain_alloc_dma = ioc->req_alloc_dma+request_buffer_sz;
-		ioc->chain_alloc_sz = chain_buffer_sz;
-
-		/*  Prime reply FIFO...  */
-		dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%p], sz=%d bytes\n",
-			ioc->name, ioc->reply_alloc, 
-			(void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
-
-		b = (unsigned long) ioc->reply_alloc;
-		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
-		aligned_mem = (u8 *) b;
-		ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
-		ioc->reply_frames_dma =
-			(ioc->reply_alloc_dma + (aligned_mem - ioc->reply_alloc));
+		memset(mem, 0, total_size);
+		ioc->alloc_total += total_size;
+		ioc->alloc = mem;
+		ioc->alloc_dma = alloc_dma;
+		ioc->alloc_sz = total_size;
+		ioc->reply_frames = (MPT_FRAME_HDR *) mem;
+		ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
+
+		alloc_dma += reply_sz;
+		mem += reply_sz;
 
-		ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF);
-	
 		/*  Request FIFO - WE manage this!  */
-		dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%p], sz=%d bytes\n",
-			ioc->name, ioc->req_alloc,
-			(void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
-
-		b = (unsigned long) ioc->req_alloc;
-		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
-		aligned_mem = (u8 *) b;
-		ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
-		ioc->req_frames_dma =
-			(ioc->req_alloc_dma + (aligned_mem - ioc->req_alloc));
 
-		ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF);
+		ioc->req_frames = (MPT_FRAME_HDR *) mem;
+		ioc->req_frames_dma = alloc_dma;
+
+		dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n",
+			 	ioc->name, mem, (void *)(ulong)alloc_dma));
+
+		ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
 
 #if defined(CONFIG_MTRR) && 0
 		/*
@@ -3559,79 +3571,93 @@
 		 *  (at least as much as we can; "size and base must be
 		 *  multiples of 4 kiB"
 		 */
-		ioc->mtrr_reg = mtrr_add(ioc->fifo_pool,
-					 ioc->fifo_pool_sz,
+		ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
+					 sz,
 					 MTRR_TYPE_WRCOMB, 1);
 		dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
-				ioc->name, ioc->fifo_pool, ioc->fifo_pool_sz));
+				ioc->name, ioc->req_frames_dma, sz));
 #endif
 
-	} /* ioc->fifo_pool == NULL */
-	
-	/* Post Reply frames to FIFO
-	 */
-	aligned_mem_dma = ioc->reply_frames_dma;
-	dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n",
-		 	ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma));
+		for (i = 0; i < ioc->req_depth; i++) {
+			alloc_dma += ioc->req_sz;
+			mem += ioc->req_sz;
+		}
 
-	for (i = 0; i < ioc->reply_depth; i++) {
-		/*  Write each address to the IOC!  */
-		CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
-		aligned_mem_dma += ioc->reply_sz;
-	}
+		ioc->ChainBuffer = mem;
+		ioc->ChainBufferDMA = alloc_dma;
 
+		dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n",
+			ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
 
-	/* Initialize Request frames linked list
-	 */
-	aligned_mem_dma = ioc->req_frames_dma;
-	aligned_mem = (u8 *) ioc->req_frames;
-	dprintk((KERN_INFO MYNAM ": %s.req_frames   @ %p[%p]\n",
-		 	ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma));
+		/* Initialize the free chain Q.
+	 	*/
 
-	spin_lock_irqsave(&ioc->FreeQlock, flags);
-	Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
-	for (i = 0; i < ioc->req_depth; i++) {
-		mf = (MPT_FRAME_HDR *) aligned_mem;
-
-		/*  Queue REQUESTs *internally*!  */
-		Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
-		aligned_mem += ioc->req_sz;
-	}
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+		Q_INIT(&ioc->FreeChainQ, MPT_FRAME_HDR);
 
+		/* Post the chain buffers to the FreeChainQ.
+	 	*/
+		mem = (u8 *)ioc->ChainBuffer;
+		for (i=0; i < num_chain; i++) {
+			mf = (MPT_FRAME_HDR *) mem;
+			Q_ADD_TAIL(&ioc->FreeChainQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
+			mem += ioc->req_sz;
+		}
+
+		/* Initialize Request frames linked list
+		 */
+		alloc_dma = ioc->req_frames_dma;
+		mem = (u8 *) ioc->req_frames;
+
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
+		Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
+		for (i = 0; i < ioc->req_depth; i++) {
+			mf = (MPT_FRAME_HDR *) mem;
+
+			/*  Queue REQUESTs *internally*!  */
+			Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
+			mem += ioc->req_sz;
+		}
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
-	if (ioc->sense_buf_pool == NULL) {
 		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
 		ioc->sense_buf_pool =
-				pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
-		if (ioc->sense_buf_pool == NULL)
+			pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
+		if (ioc->sense_buf_pool == NULL) {
+			printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
+				ioc->name);
 			goto out_fail;
+		}
 
 		ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
 		ioc->alloc_total += sz;
+		dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
+ 			ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
+
+	}
+
+	/* Post Reply frames to FIFO
+	 */
+	alloc_dma = ioc->alloc_dma;
+	dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
+	 	ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
+
+	for (i = 0; i < ioc->reply_depth; i++) {
+		/*  Write each address to the IOC!  */
+		CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
+		alloc_dma += ioc->reply_sz;
 	}
 
 	return 0;
 
 out_fail:
-	if (ioc->fifo_pool != NULL) {
+	if (ioc->alloc != NULL) {
+		sz = ioc->alloc_sz;
 		pci_free_consistent(ioc->pcidev,
-				ioc->fifo_pool_sz,
-				ioc->fifo_pool, ioc->fifo_pool_dma);
+				sz,
+				ioc->alloc, ioc->alloc_dma);
 		ioc->reply_frames = NULL;
-		ioc->reply_alloc = NULL;
 		ioc->req_frames = NULL;
-		ioc->req_alloc = NULL;
-		ioc->chain_alloc = NULL;
-		ioc->fifo_pool = NULL;
-		ioc->alloc_total -= ioc->fifo_pool_sz;
-#if defined(CONFIG_MTRR) && 0
-		if (ioc->mtrr_reg > 0) {
-			mtrr_del(ioc->mtrr_reg, 0, 0);
-			dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n",
-					ioc->name));
-		}
-#endif
+		ioc->alloc_total -= sz;
 	}
 	if (ioc->sense_buf_pool != NULL) {
 		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
@@ -3693,8 +3719,8 @@
 	if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 		failcnt++;
 
-	dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n",
-			ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
+	dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
+			ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
 
 	/* Read doorbell and check for active bit */
 	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
@@ -3728,7 +3754,7 @@
 				failcnt++;
 		}
 
-		dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
+		dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
 		DBG_DUMP_REQUEST_FRAME_HDR(req)
 
 		dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
@@ -3783,7 +3809,7 @@
 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
 				break;
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 			count++;
 		}
 	} else {
@@ -3833,7 +3859,7 @@
 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
 				break;
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 			count++;
 		}
 	} else {
@@ -3935,7 +3961,7 @@
 	}
 #endif
 
-	dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
+	dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
 	DBG_DUMP_REPLY_FRAME(mptReply)
 
 	dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
@@ -4282,9 +4308,11 @@
 				pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
 				pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
 
-				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 )
+				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
 					ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
-
+					dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+						ioc->name, pPP0->Capabilities));
+				}
 				ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
 				data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
 				if (data) {
@@ -4907,8 +4935,8 @@
 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
 {
 	ToolboxIstwiReadWriteRequest_t	*pReq;
-	struct pci_dev	*pdev;
 	MPT_FRAME_HDR	*mf;
+	struct pci_dev	*pdev;
 	unsigned long	 flags;
 	int		 rc;
 	u32		 flagsLength;
@@ -5226,12 +5254,6 @@
 
 			if (drvname)
 				len += sprintf(buf+len, "  Fusion MPT %s driver\n", drvname);
-			/*
-			 *	Handle isense special case, because it
-			 *	doesn't do a formal mpt_register call.
-			 */
-			if (isense_idx == ii)
-				len += sprintf(buf+len, "  Fusion MPT isense driver\n");
 		}
 	}
 
@@ -5286,7 +5308,7 @@
 	len += sprintf(buf+len, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
 
 	len += sprintf(buf+len, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
-					(void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma);
+					(void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
 	/*
 	 *  Rounding UP to nearest 4-kB boundary here...
 	 */
@@ -5298,8 +5320,8 @@
 					4*ioc->facts.RequestFrameSize,
 					ioc->facts.GlobalCredits);
 
-	len += sprintf(buf+len, "  ReplyFrames   @ 0x%p (Dma @ 0x%p)\n",
-					(void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma);
+	len += sprintf(buf+len, "  Frames   @ 0x%p (Dma @ 0x%p)\n",
+					(void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
 	sz = (ioc->reply_sz * ioc->reply_depth) + 128;
 	len += sprintf(buf+len, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
 					ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
@@ -5592,7 +5614,7 @@
 	}
 
 	evStr = EventDescriptionStr(event, evData0);
-	dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
+	devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
 			ioc->name,
 			evStr,
 			event));
@@ -5664,7 +5686,7 @@
 	 */
 	for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
 		if (MptEvHandlers[ii]) {
-			dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
+			devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
 					ioc->name, ii));
 			r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
 			handlers++;
@@ -5677,8 +5699,8 @@
 	 */
 	if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
 		if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
-			printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
-					ioc->name, ii);
+			devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+					ioc->name, ii));
 		}
 	}
 
@@ -5702,9 +5724,8 @@
 		"FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
 	};
 	u8 subcl = (log_info >> 24) & 0x7;
-//	u32 SubCl = log_info & 0x27000000;
 
-	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
+	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
 			ioc->name, log_info, subcl_str[subcl]);
 }
 
@@ -5907,50 +5928,6 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
- *	OpCode strings from the (optional) isense module.
- *	@ascqTable: Pointer to ASCQ_Table_t structure
- *	@ascqtbl_sz: Number of entries in ASCQ_Table
- *	@opsTable: Pointer to array of SCSI OpCode strings (char pointers)
- *
- *	Specialized driver registration routine for the isense driver.
- */
-int
-mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable)
-{
-	int r = 0;
-
-	if (ascqTable && ascqtbl_sz && opsTable) {
-		mpt_v_ASCQ_TablePtr = ascqTable;
-		mpt_ASCQ_TableSz = ascqtbl_sz;
-		mpt_ScsiOpcodesPtr = opsTable;
-		printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
-		isense_idx = last_drv_idx;
-		r = 1;
-	}
-	return r;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
- *	OpCode strings from the isense driver.
- *
- *	Specialized driver deregistration routine for the isense driver.
- */
-void
-mpt_deregister_ascqops_strings(void)
-{
-	mpt_v_ASCQ_TablePtr = NULL;
-	mpt_ASCQ_TableSz = 0;
-	mpt_ScsiOpcodesPtr = NULL;
-	printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
-	isense_idx = -1;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
 EXPORT_SYMBOL(ioc_list);
 EXPORT_SYMBOL(mpt_proc_root_dir);
 EXPORT_SYMBOL(DmpService);
@@ -5981,13 +5958,6 @@
 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
-
-EXPORT_SYMBOL(mpt_register_ascqops_strings);
-EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
-EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
-EXPORT_SYMBOL(mpt_ASCQ_TableSz);
-EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
-
 
 static struct pci_driver mptbase_driver = {
 	.name		= "mptbase",
diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
--- a/drivers/message/fusion/mptbase.h	2004-06-23 07:48:43 -07:00
+++ b/drivers/message/fusion/mptbase.h	2004-08-26 15:41:13 -07:00
@@ -60,8 +60,6 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 
-#include "scsi3.h"		/* SCSI defines */
-
 #include "lsi/mpi_type.h"
 #include "lsi/mpi.h"		/* Fusion MPI(nterface) basic defs */
 #include "lsi/mpi_ioc.h"	/* Fusion MPT IOC(ontroller) defs */
@@ -85,8 +83,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2004 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.01.09"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.09"
+#define MPT_LINUX_VERSION_COMMON	"3.01.16"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.16"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -320,17 +318,6 @@
 	struct _Q_ITEM	*tail;
 } Q_TRACKER;
 
-typedef struct _MPT_DONE_Q {
-	struct _MPT_DONE_Q	*forw;
-	struct _MPT_DONE_Q	*back;
-	void			*argp;
-} MPT_DONE_Q;
-
-typedef struct _DONE_Q_TRACKER {
-	MPT_DONE_Q	*head;
-	MPT_DONE_Q	*tail;
-} DONE_Q_TRACKER;
-
 /*
  *  Chip-specific stuff... FC929 delineates break between
  *  FC and Parallel SCSI parts. Do NOT re-order.
@@ -403,6 +390,11 @@
 	void			*tail;
 } ScsiCmndTracker;
 
+/* VirtDevice negoFlags field */
+#define MPT_TARGET_NO_NEGO_WIDE		0x01
+#define MPT_TARGET_NO_NEGO_SYNC		0x02
+#define MPT_TARGET_NO_NEGO_QAS		0x04
+#define MPT_TAPE_NEGO_IDP     		0x08
 
 /*
  *	VirtDevice - FC LUN device or SCSI target device
@@ -420,8 +412,8 @@
 	u8			 bus_id;
 	u8			 minSyncFactor;	/* 0xFF is async */
 	u8			 maxOffset;	/* 0 if async */
-	u8			 maxWidth;	/* 0 if narrow, 1 if wide*/
-	u8			 negoFlags;	/* bit field, 0 if WDTR/SDTR/QAS allowed */
+	u8			 maxWidth;	/* 0 if narrow, 1 if wide */
+	u8			 negoFlags;	/* bit field, see above */
 	u8			 raidVolume;	/* set, if RAID Volume */
 	u8			 type;		/* byte 0 of Inquiry data */
 	u8			 cflags;	/* controller flags */
@@ -460,10 +452,6 @@
 #define MPT_TARGET_FLAGS_VALID_56	0x10
 #define MPT_TARGET_FLAGS_SAF_TE_ISSUED	0x20
 
-#define MPT_TARGET_NO_NEGO_WIDE		0x01
-#define MPT_TARGET_NO_NEGO_SYNC		0x02
-#define MPT_TARGET_NO_NEGO_QAS		0x04
-
 typedef struct _VirtDevTracker {
 	struct _VirtDevice	*head;
 	struct _VirtDevice	*tail;
@@ -523,6 +511,7 @@
 	u8			 target;	/* target for reset */
 	void 			*tmPtr;
 	struct timer_list	 TMtimer;	/* timer function for this adapter */
+	struct semaphore	 sem_ioc;
 } MPT_IOCTL;
 
 /*
@@ -600,25 +589,30 @@
 	int			 alloc_total;
 	u32			 last_state;
 	int			 active;
-	u8			*fifo_pool;	/* dma pool for fifo's */
-	dma_addr_t		 fifo_pool_dma;
-	int			 fifo_pool_sz;	/* allocated size */
-	u8			*chain_alloc;	/* chain buffer alloc ptr */
-	dma_addr_t		chain_alloc_dma;
-	int			chain_alloc_sz;
-	u8			*reply_alloc;	/* Reply frames alloc ptr */
-	dma_addr_t		 reply_alloc_dma;
+	u8			*alloc;		/* frames alloc ptr */
+	dma_addr_t		 alloc_dma;
+	u32			 alloc_sz;
 	MPT_FRAME_HDR		*reply_frames;	/* Reply msg frames - rounded up! */
-	dma_addr_t		 reply_frames_dma;
 	u32			 reply_frames_low_dma;
 	int			 reply_depth;	/* Num Allocated reply frames */
 	int			 reply_sz;	/* Reply frame size */
+	int			 num_chain;	/* Number of chain buffers */
+		/* Pool of buffers for chaining. ReqToChain
+		 * and ChainToChain track index of chain buffers.
+		 * ChainBuffer (DMA) virt/phys addresses.
+		 * FreeChainQ (lock) locking mechanisms.
+		 */
+	int			*ReqToChain;
+	int			*RequestNB;
+	int			*ChainToChain;
+	u8			*ChainBuffer;
+	dma_addr_t		 ChainBufferDMA;
+	MPT_Q_TRACKER		 FreeChainQ;
+	spinlock_t		 FreeChainQlock;
 	CHIP_TYPE		 chip_type;
 		/* We (host driver) get to manage our own RequestQueue! */
-	u8			*req_alloc;	/* Request frames alloc ptr */
-	dma_addr_t		 req_alloc_dma;
-	MPT_FRAME_HDR		*req_frames;	/* Request msg frames - rounded up! */
 	dma_addr_t		 req_frames_dma;
+	MPT_FRAME_HDR		*req_frames;	/* Request msg frames - rounded up! */
 	u32			 req_frames_low_dma;
 	int			 req_depth;	/* Number of request frames */
 	int			 req_sz;	/* Request frame size (bytes) */
@@ -661,6 +655,7 @@
 #else
 	u32			 mfcnt;
 #endif
+	u32			 NB_for_64_byte_frame;       
 	u32			 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)];
 	u16			 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)];
 	IOCFactsReply_t		 facts;
@@ -674,8 +669,10 @@
 	u8			 FirstWhoInit;
 	u8			 upload_fw;	/* If set, do a fw upload */
 	u8			 reload_fw;	/* Force a FW Reload on next reset */
-	u8			 pad1[5];
+	u8			 NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */     
+	u8			 pad1[4];
 	struct list_head	 list; 
+	struct net_device	*netdev;
 } MPT_ADAPTER;
 
 
@@ -757,10 +754,10 @@
 #define dexitprintk(x)
 #endif
 
-#ifdef MPT_DEBUG_RESET
-#define drsprintk(x)  printk x
+#if defined MPT_DEBUG_FAIL || defined (MPT_DEBUG_SG)
+#define dfailprintk(x) printk x
 #else
-#define drsprintk(x)
+#define dfailprintk(x)
 #endif
 
 #ifdef MPT_DEBUG_HANDSHAKE
@@ -769,11 +766,34 @@
 #define dhsprintk(x)
 #endif
 
+#ifdef MPT_DEBUG_EVENTS
+#define devtprintk(x)  printk x
+#else
+#define devtprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_RESET
+#define drsprintk(x)  printk x
+#else
+#define drsprintk(x)
+#endif
+
 //#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME)
 #if defined(MPT_DEBUG_MSG_FRAME)
 #define dmfprintk(x)  printk x
+#define DBG_DUMP_REQUEST_FRAME(mfp) \
+	{	int  i, n = 24;						\
+		u32 *m = (u32 *)(mfp);					\
+		for (i=0; i<n; i++) {					\
+			if (i && ((i%8)==0))				\
+				printk("\n");				\
+			printk("%08x ", le32_to_cpu(m[i]));		\
+		}							\
+		printk("\n");						\
+	}
 #else
 #define dmfprintk(x)
+#define DBG_DUMP_REQUEST_FRAME(mfp)
 #endif
 
 #ifdef MPT_DEBUG_IRQ
@@ -794,13 +814,18 @@
 #define ddlprintk(x)
 #endif
 
-
 #ifdef MPT_DEBUG_DV
 #define ddvprintk(x)  printk x
 #else
 #define ddvprintk(x)
 #endif
 
+#ifdef MPT_DEBUG_NEGO
+#define dnegoprintk(x)  printk x
+#else
+#define dnegoprintk(x)
+#endif
+
 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
 #define ddvtprintk(x)  printk x
 #else
@@ -813,10 +838,40 @@
 #define dctlprintk(x)
 #endif
 
-#ifdef MPT_DEBUG_RESET
+#ifdef MPT_DEBUG_REPLY
+#define dreplyprintk(x) printk x
+#else
+#define dreplyprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_TM
 #define dtmprintk(x) printk x
+#define DBG_DUMP_TM_REQUEST_FRAME(mfp) \
+	{	u32 *m = (u32 *)(mfp);					\
+		int  i, n = 13;						\
+		printk("TM_REQUEST:\n");				\
+		for (i=0; i<n; i++) {					\
+			if (i && ((i%8)==0))				\
+				printk("\n");				\
+			printk("%08x ", le32_to_cpu(m[i]));		\
+		}							\
+		printk("\n");						\
+	}
+#define DBG_DUMP_TM_REPLY_FRAME(mfp) \
+	{	u32 *m = (u32 *)(mfp);					\
+		int  i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16;	\
+		printk("TM_REPLY MessageLength=%d:\n", n);		\
+		for (i=0; i<n; i++) {					\
+			if (i && ((i%8)==0))				\
+				printk("\n");				\
+			printk(" %08x", le32_to_cpu(m[i]));		\
+		}							\
+		printk("\n");						\
+	}
 #else
 #define dtmprintk(x)
+#define DBG_DUMP_TM_REQUEST_FRAME(mfp)
+#define DBG_DUMP_TM_REPLY_FRAME(mfp)
 #endif
 
 #ifdef MPT_DEBUG_NEH
@@ -907,6 +962,10 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
+#define SCSI_STD_SENSE_BYTES    18
+#define SCSI_STD_INQUIRY_BYTES  36
+#define SCSI_MAX_INQUIRY_BYTES  96
+
 /*
  * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
  * Private to the driver.
@@ -950,17 +1009,6 @@
 	int			  port;
 	u32			  pad0;
 	struct scsi_cmnd	**ScsiLookup;
-		/* Pool of buffers for chaining. ReqToChain
-		 * and ChainToChain track index of chain buffers.
-		 * ChainBuffer (DMA) virt/phys addresses.
-		 * FreeChainQ (lock) locking mechanisms.
-		 */
-	int			 *ReqToChain;
-	int			 *ChainToChain;
-	u8			 *ChainBuffer;
-	dma_addr_t		  ChainBufferDMA;
-	MPT_Q_TRACKER		  FreeChainQ;
-	spinlock_t		  FreeChainQlock;
 	u32			  qtag_tick;
 	VirtDevice		**Targets;
 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
@@ -969,23 +1017,15 @@
 		/* Pool of memory for holding SCpnts before doing
 		 * OS callbacks. freeQ is the free pool.
 		 */
-	u8			 *memQ;
-	DONE_Q_TRACKER		  freeQ;
-	DONE_Q_TRACKER		  doneQ;		/* Holds Linux formmatted requests */
-	DONE_Q_TRACKER		  pendingQ;		/* Holds MPI formmatted requests */
 	MPT_Q_TRACKER		  taskQ;		/* TM request Q */
-	spinlock_t		  freedoneQlock;
 	int			  taskQcnt;
-	int			  num_chain;		/* Number of chain buffers */
-	int			  max_sge;		/* Max No of SGE*/
-	u8			  numTMrequests;
 	u8			  tmPending;
 	u8			  resetPending;
 	u8			  is_spi;		/* Parallel SCSI i/f */
 	u8			  negoNvram;		/* DV disabled, nego NVRAM */
 	u8			  is_multipath;		/* Multi-path compatible */
 	u8                        tmState;
-	u8			  rsvd[1];
+	u8			  rsvd[2];
 	MPT_FRAME_HDR		 *tmPtr;		/* Ptr to TM request*/
 	MPT_FRAME_HDR		 *cmdPtr;		/* Ptr to nonOS request */
 	struct scsi_cmnd	 *abortSCpnt;
@@ -1055,10 +1095,8 @@
 extern void	 mpt_reset_deregister(int cb_idx);
 extern int	 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx);
 extern void	 mpt_device_driver_deregister(int cb_idx);
-extern int	 mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable);
-extern void	 mpt_deregister_ascqops_strings(void);
 extern MPT_FRAME_HDR	*mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc);
-extern void	 mpt_free_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
+extern void	 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
 extern void	 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
 extern void	 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
 extern void	 mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr);
@@ -1085,10 +1123,6 @@
 
 extern int		  mpt_lan_index;	/* needed by mptlan.c */
 extern int		  mpt_stm_index;	/* needed by mptstm.c */
-
-extern void		 *mpt_v_ASCQ_TablePtr;
-extern const char	**mpt_ScsiOpcodesPtr;
-extern int		  mpt_ASCQ_TableSz;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #endif		/* } __KERNEL__ */
diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
--- a/drivers/message/fusion/mptctl.c	2004-06-26 15:44:19 -07:00
+++ b/drivers/message/fusion/mptctl.c	2004-08-26 15:41:13 -07:00
@@ -111,7 +111,6 @@
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 static int mptctl_id = -1;
-static struct semaphore mptctl_syscall_sem_ioc[MPT_MAX_ADAPTERS];
 
 static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
 
@@ -140,6 +139,9 @@
 static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
 static int mptctl_hp_targetinfo(unsigned long arg);
 
+static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+static void mptctl_remove(struct pci_dev *);
+
 /*
  * Private function calls.
  */
@@ -208,10 +210,10 @@
 	}
 
 	if (nonblock) {
-		if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id]))
+		if (down_trylock(&ioc->ioctl->sem_ioc))
 			rc = -EAGAIN;
 	} else {
-		if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
+		if (down_interruptible(&ioc->ioctl->sem_ioc))
 			rc = -ERESTARTSYS;
 	}
 	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -445,7 +447,7 @@
 
 		mptctl_free_tm_flags(ioctl->ioc);
 		del_timer(&ioctl->TMtimer);
-		mpt_free_msg_frame(mptctl_id, ioctl->ioc, mf);
+		mpt_free_msg_frame(ioctl->ioc, mf);
 		ioctl->tmPtr = NULL;
 	}
 
@@ -482,7 +484,7 @@
 
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 
-	hd->tmState = TM_STATE_ERROR;
+	hd->tmState = TM_STATE_NONE;
 	hd->tmPending = 0;
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
@@ -520,7 +522,7 @@
 		if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){
 			ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
 			del_timer(&ioctl->TMtimer);
-			mpt_free_msg_frame(mptctl_id, ioc, ioctl->tmPtr);
+			mpt_free_msg_frame(ioc, ioctl->tmPtr);
 		}
 
 	} else {
@@ -630,8 +632,7 @@
 	else
 		ret = -EINVAL;
 
-
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
@@ -1807,7 +1808,6 @@
 	struct buflist	bufOut; /* data Out buffer */
 	dma_addr_t	dma_addr_in;
 	dma_addr_t	dma_addr_out;
-	int		dir;	/* PCI data direction */
 	int		sgSize = 0;	/* Num SG elements */
 	int		iocnum, flagsLength;
 	int		sz, rc = 0;
@@ -2117,9 +2117,9 @@
 
 		/* Set up the dataOut memory allocation */
 		if (karg.dataOutSize > 0) {
-			dir = PCI_DMA_TODEVICE;
 			if (karg.dataInSize > 0) {
 				flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+						MPI_SGE_FLAGS_END_OF_BUFFER |
 						MPI_SGE_FLAGS_DIRECTION |
 						mpt_addr_size() )
 						<< MPI_SGE_FLAGS_SHIFT;
@@ -2158,7 +2158,6 @@
 		}
 
 		if (karg.dataInSize > 0) {
-			dir = PCI_DMA_FROMDEVICE;
 			flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
 			flagsLength |= karg.dataInSize;
 
@@ -2196,6 +2195,7 @@
 	add_timer(&ioc->ioctl->timer);
 
 	if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
+		DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
 		rc = mpt_send_handshake_request(mptctl_id, ioc,
 				sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
 		if (rc == 0) {
@@ -2206,7 +2206,7 @@
 			del_timer(&ioc->ioctl->timer);
 			ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
 			ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;
-			mpt_free_msg_frame(mptctl_id, ioc, mf);
+			mpt_free_msg_frame(ioc, mf);
 		}
 	} else {
 		mpt_put_msg_frame(mptctl_id, ioc, mf);
@@ -2324,7 +2324,7 @@
 	 * otherwise, failure occured after mf acquired.
 	 */
 	if (mf)
-		mpt_free_msg_frame(mptctl_id, ioc, mf);
+		mpt_free_msg_frame(ioc, mf);
 
 	return rc;
 }
@@ -2738,7 +2738,7 @@
 
 	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
 
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
@@ -2792,55 +2792,91 @@
 	 */
 	ret = mptctl_do_mpt_command (karg, &uarg->MF);
 
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
 
 #endif
 
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-int __init mptctl_init(void)
+/*
+ *	mptctl_probe - Installs ioctl devices per bus.
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *	Returns 0 for success, non-zero for failure.
+ *
+ */
+
+static int
+mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int err;
-	int i;
-	int where = 1;
 	int sz;
 	u8 *mem;
-	MPT_ADAPTER *ioc = NULL;
-	int iocnum;
+	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 
-	show_mptmod_ver(my_NAME, my_VERSION);
+	/*
+	 * Allocate and inite a MPT_IOCTL structure
+	*/
+	sz = sizeof (MPT_IOCTL);
+	mem = kmalloc(sz, GFP_KERNEL);
+	if (mem == NULL) {
+		err = -ENOMEM;
+		goto out_fail;
+	}
 
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		sema_init(&mptctl_syscall_sem_ioc[i], 1);
+	memset(mem, 0, sz);
+	ioc->ioctl = (MPT_IOCTL *) mem;
+	ioc->ioctl->ioc = ioc;
+	init_timer (&ioc->ioctl->timer);
+	ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
+	ioc->ioctl->timer.function = mptctl_timer_expired;
+	init_timer (&ioc->ioctl->TMtimer);
+	ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
+	ioc->ioctl->TMtimer.function = mptctl_timer_expired;
+	sema_init(&ioc->ioctl->sem_ioc, 1);
+	return 0;
 
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			/* This adapter instance is found.
-			 * Allocate and inite a MPT_IOCTL structure
-			 */
-			sz = sizeof (MPT_IOCTL);
-			mem = kmalloc(sz, GFP_KERNEL);
-			if (mem == NULL) {
-				err = -ENOMEM;
-				goto out_fail;
-			}
-
-			memset(mem, 0, sz);
-			ioc->ioctl = (MPT_IOCTL *) mem;
-			ioc->ioctl->ioc = ioc;
-			init_timer (&ioc->ioctl->timer);
-			ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
-			ioc->ioctl->timer.function = mptctl_timer_expired;
-			init_timer (&ioc->ioctl->TMtimer);
-			ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
-			ioc->ioctl->TMtimer.function = mptctl_timer_expired;
-		}
+out_fail:
+
+	mptctl_remove(pdev);
+	return err;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mptctl_remove - Removed ioctl devices
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *
+ */
+static void
+mptctl_remove(struct pci_dev *pdev)
+{
+	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+
+	kfree ( ioc->ioctl );
+}
+
+static struct mpt_pci_driver mptctl_driver = {
+  .probe		= mptctl_probe,
+  .remove		= mptctl_remove,
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int __init mptctl_init(void)
+{
+	int err;
+	int where = 1;
+
+	show_mptmod_ver(my_NAME, my_VERSION);
+
+	if(mpt_device_driver_register(&mptctl_driver,
+	  MPTCTL_DRIVER) != 0 ) {
+		dprintk((KERN_INFO MYNAM
+		": failed to register dd callbacks\n"));
 	}
 
 #ifdef CONFIG_COMPAT
@@ -2922,29 +2958,14 @@
 	unregister_ioctl32_conversion(HP_GETTARGETINFO);
 #endif
 
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			if (ioc->ioctl) {
-				kfree ( ioc->ioctl );
-				ioc->ioctl = NULL;
-			}
-		}
-	}
+	mpt_device_driver_deregister(MPTCTL_DRIVER);
+
 	return err;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-void mptctl_exit(void)
+static void mptctl_exit(void)
 {
-	int i;
-	MPT_ADAPTER *ioc;
-	int iocnum;
-
 	misc_deregister(&mptctl_miscdev);
 	printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
 			 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
@@ -2957,6 +2978,8 @@
 	mpt_deregister(mptctl_id);
 	printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
 
+        mpt_device_driver_deregister(MPTCTL_DRIVER);
+
 #ifdef CONFIG_COMPAT
 	unregister_ioctl32_conversion(MPTIOCINFO);
 	unregister_ioctl32_conversion(MPTIOCINFO1);
@@ -2973,20 +2996,6 @@
 	unregister_ioctl32_conversion(HP_GETTARGETINFO);
 #endif
 
-	/* Free allocated memory */
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			if (ioc->ioctl) {
-				kfree ( ioc->ioctl );
-				ioc->ioctl = NULL;
-			}
-		}
-	}
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff -Nru a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
--- a/drivers/message/fusion/mptlan.c	2004-06-23 07:48:44 -07:00
+++ b/drivers/message/fusion/mptlan.c	2004-07-02 10:07:04 -07:00
@@ -177,11 +177,9 @@
 static u32 max_buckets_out = 127;
 static u32 tx_max_out_p = 127 - 16;
 
-static struct net_device *mpt_landev[MPT_MAX_ADAPTERS+1];
-
 #ifdef QLOGIC_NAA_WORKAROUND
 static struct NAA_Hosed *mpt_bad_naa = NULL;
-rwlock_t bad_naa_lock;
+rwlock_t bad_naa_lock = RW_LOCK_UNLOCKED;
 #endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -203,7 +201,7 @@
 static int
 lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 {
-	struct net_device *dev = mpt_landev[ioc->id];
+	struct net_device *dev = ioc->netdev;
 	int FreeReqFrame = 0;
 
 	dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
@@ -336,7 +334,7 @@
 static int
 mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-	struct net_device *dev = mpt_landev[ioc->id];
+	struct net_device *dev = ioc->netdev;
 	struct mpt_lan_priv *priv = netdev_priv(dev);
 
 	dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n",
@@ -1334,7 +1332,7 @@
 		if (pSimple == NULL) {
 /**/			printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",
 /**/				__FUNCTION__);
-			mpt_free_msg_frame(LanCtx, mpt_dev, mf);
+			mpt_free_msg_frame(mpt_dev, mf);
 			goto out;
 		}
 
@@ -1451,20 +1449,74 @@
 	return dev;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int __init mpt_lan_init (void)
+static int
+mptlan_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	struct net_device *dev;
-	MPT_ADAPTER *p;
-	int i, j;
+	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
+	struct net_device	*dev;
+	int			i;
+
+	for (i = 0; i < ioc->facts.NumberOfPorts; i++) {
+		printk(KERN_INFO MYNAM ": %s: PortNum=%x, "
+		       "ProtocolFlags=%02Xh (%c%c%c%c)\n",
+		       ioc->name, ioc->pfacts[i].PortNumber,
+		       ioc->pfacts[i].ProtocolFlags,
+		       MPT_PROTOCOL_FLAGS_c_c_c_c(
+			       ioc->pfacts[i].ProtocolFlags));
+
+		if (!(ioc->pfacts[i].ProtocolFlags &
+					MPI_PORTFACTS_PROTOCOL_LAN)) {
+			printk(KERN_INFO MYNAM ": %s: Hmmm... LAN protocol "
+			       "seems to be disabled on this adapter port!\n",
+			       ioc->name);
+			continue;
+		}
 
-	show_mptmod_ver(LANAME, LANVER);
+		dev = mpt_register_lan_device(ioc, i);
+		if (!dev) {
+			printk(KERN_ERR MYNAM ": %s: Unable to register "
+			       "port%d as a LAN device\n", ioc->name,
+			       ioc->pfacts[i].PortNumber);
+			continue;
+		}
+		
+		printk(KERN_INFO MYNAM ": %s: Fusion MPT LAN device "
+		       "registered as '%s'\n", ioc->name, dev->name);
+		printk(KERN_INFO MYNAM ": %s/%s: "
+		       "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+		       IOC_AND_NETDEV_NAMES_s_s(dev),
+		       dev->dev_addr[0], dev->dev_addr[1],
+		       dev->dev_addr[2], dev->dev_addr[3],
+		       dev->dev_addr[4], dev->dev_addr[5]);
+	
+		ioc->netdev = dev;
 
-#ifdef QLOGIC_NAA_WORKAROUND
-	/* Init the global r/w lock for the bad_naa list. We want to do this
-	   before any boards are initialized and may be used. */
-	rwlock_init(&bad_naa_lock);
-#endif
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static void
+mptlan_remove(struct pci_dev *pdev)
+{
+	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
+	struct net_device	*dev = ioc->netdev;
+
+	if(dev != NULL) {
+		unregister_netdev(dev);
+		free_netdev(dev);
+	}
+}
+
+static struct mpt_pci_driver mptlan_driver = {
+	.probe		= mptlan_probe,
+	.remove		= mptlan_remove,
+};
+
+static int __init mpt_lan_init (void)
+{
+	show_mptmod_ver(LANAME, LANVER);
 
 	if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) <= 0) {
 		printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n");
@@ -1476,87 +1528,31 @@
 
 	dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx));
 
-	if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset) == 0) {
-		dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
-	} else {
+	if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) {
 		printk(KERN_ERR MYNAM ": Eieee! unable to register a reset "
 		       "handler with mptbase! The world is at an end! "
 		       "Everything is fading to black! Goodbye.\n");
 		return -EBUSY;
 	}
 
-	for (j = 0; j < MPT_MAX_ADAPTERS; j++) {
-		mpt_landev[j] = NULL;
-	}
-
-	list_for_each_entry(p, &ioc_list, list) {
-		for (i = 0; i < p->facts.NumberOfPorts; i++) {
-			printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n",
-					p->name,
-					p->pfacts[i].PortNumber,
-					p->pfacts[i].ProtocolFlags,
-					MPT_PROTOCOL_FLAGS_c_c_c_c(p->pfacts[i].ProtocolFlags));
-
-			if (!(p->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
-				printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n",
-						p->name);
-				continue;
-			}
-
-			dev = mpt_register_lan_device (p, i);
-			if (!dev) {
-				printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n",
-						p->name,
-						p->pfacts[i].PortNumber);
-			}
-			printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n",
-					p->name, dev->name);
-			printk (KERN_INFO MYNAM ": %s/%s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-					IOC_AND_NETDEV_NAMES_s_s(dev),
-					dev->dev_addr[0], dev->dev_addr[1],
-					dev->dev_addr[2], dev->dev_addr[3],
-					dev->dev_addr[4], dev->dev_addr[5]);
-//					printk (KERN_INFO MYNAM ": %s/%s: Max_TX_outstanding = %d\n",
-//							IOC_AND_NETDEV_NAMES_s_s(dev),
-//							NETDEV_TO_LANPRIV_PTR(dev)->tx_max_out);
-			j = p->id;
-			mpt_landev[j] = dev;
-			dlprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n",
-					dev, j,  mpt_landev[j]));
-
-		}
-	}
-
+	dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
+	
+	if (mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER))
+		dprintk((KERN_INFO MYNAM ": failed to register dd callbacks\n"));
 	return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void __exit mpt_lan_exit(void)
 {
-	int i;
-
+	mpt_device_driver_deregister(MPTLAN_DRIVER);
 	mpt_reset_deregister(LanCtx);
 
-	for (i = 0; mpt_landev[i] != NULL; i++) {
-		struct net_device *dev = mpt_landev[i];
-
-		printk (KERN_INFO ": %s/%s: Fusion MPT LAN device unregistered\n",
-			       IOC_AND_NETDEV_NAMES_s_s(dev));
-		unregister_netdev(dev);
-		free_netdev(dev);
-		mpt_landev[i] = NULL;
-	}
-
 	if (LanCtx >= 0) {
 		mpt_deregister(LanCtx);
 		LanCtx = -1;
 		mpt_lan_index = 0;
 	}
-
-	/* deregister any send/receive handler structs. I2Oism? */
 }
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 module_init(mpt_lan_init);
 module_exit(mpt_lan_exit);
diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c	2004-07-12 01:01:06 -07:00
+++ b/drivers/message/fusion/mptscsih.c	2004-08-26 15:41:13 -07:00
@@ -86,7 +86,6 @@
 
 #include "mptbase.h"
 #include "mptscsih.h"
-#include "isense.h"
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #define my_NAME		"Fusion MPT SCSI Host driver"
@@ -100,6 +99,7 @@
 /* Set string for command line args from insmod */
 #ifdef MODULE
 char *mptscsih = NULL;
+MODULE_PARM(mptscsih, "s");
 #endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -114,6 +114,7 @@
 #define MPT_SCANDV_SOME_ERROR		(0x00000004)
 #define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
 #define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
+#define MPT_SCANDV_FALLBACK		(0x00000020)
 
 #define MPT_SCANDV_MAX_RETRIES		(10)
 
@@ -161,15 +162,12 @@
 static void	mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
 static int	mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 
-static int	mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt,
+static int	mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
 				 SCSIIORequest_t *pReq, int req_idx);
-static void	mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
-static int	mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
+static void	mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
 static void	copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 static int	mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
 static u32	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
-static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
-static void	post_pendingQ_commands(MPT_SCSI_HOST *hd);
 
 static int	mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
 static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
@@ -178,7 +176,7 @@
 static int	mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
 static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
-void		mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
+static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
 static void	mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
 static void	mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
 static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
@@ -246,6 +244,7 @@
 static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
 static int scandv_wait_done = 1;
 
+
 /* Driver default setup
  */
 static struct mptscsih_driver_setup
@@ -323,44 +322,47 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptscsih_getFreeChainBuffes - Function to get a free chain
+ *	mptscsih_getFreeChainBuffer - Function to get a free chain
  *	from the MPT_SCSI_HOST FreeChainQ.
- *	@hd: Pointer to the MPT_SCSI_HOST instance
+ *	@ioc: Pointer to MPT_ADAPTER structure
  *	@req_idx: Index of the SCSI IO request frame. (output)
  *
  *	return SUCCESS or FAILED
  */
 static inline int
-mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
+mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
 {
 	MPT_FRAME_HDR *chainBuf;
 	unsigned long flags;
 	int rc;
 	int chain_idx;
 
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
+	dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
+			ioc->name));
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	if (!Q_IS_EMPTY(&ioc->FreeChainQ)) {
 
 		int offset;
 
-		chainBuf = hd->FreeChainQ.head;
+		chainBuf = ioc->FreeChainQ.head;
 		Q_DEL_ITEM(&chainBuf->u.frame.linkage);
-		offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
-		chain_idx = offset / hd->ioc->req_sz;
+		offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
+		chain_idx = offset / ioc->req_sz;
 		rc = SUCCESS;
+		dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
+			ioc->name, *retIndex, chainBuf));
 	}
 	else {
 		rc = FAILED;
 		chain_idx = MPT_HOST_NO_CHAIN;
+		dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
+			ioc->name));
 	}
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 
 	*retIndex = chain_idx;
 
-	dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
-			hd->ioc->name, *retIndex, chainBuf));
-
 	return rc;
 } /* mptscsih_getFreeChainBuffer() */
 
@@ -368,14 +370,14 @@
 /*
  *	mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
  *	SCSIIORequest_t Message Frame.
- *	@hd: Pointer to MPT_SCSI_HOST structure
+ *	@ioc: Pointer to MPT_ADAPTER structure
  *	@SCpnt: Pointer to scsi_cmnd structure
  *	@pReq: Pointer to SCSIIORequest_t structure
  *
  *	Returns ...
  */
 static int
-mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt,
+mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
 		SCSIIORequest_t *pReq, int req_idx)
 {
 	char 	*psge;
@@ -391,6 +393,7 @@
 	int	 newIndex;
 	int	 ii;
 	dma_addr_t v2;
+	u32	RequestNB;
 
 	sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
 	if (sgdir == MPI_SCSIIO_CONTROL_WRITE)  {
@@ -400,25 +403,25 @@
 	}
 
 	psge = (char *) &pReq->SGL;
-	frm_sz = hd->ioc->req_sz;
+	frm_sz = ioc->req_sz;
 
 	/* Map the data portion, if any.
 	 * sges_left  = 0 if no data transfer.
 	 */
 	if ( (sges_left = SCpnt->use_sg) ) {
-		sges_left = pci_map_sg(hd->ioc->pcidev,
+		sges_left = pci_map_sg(ioc->pcidev,
 			       (struct scatterlist *) SCpnt->request_buffer,
  			       SCpnt->use_sg,
 			       SCpnt->sc_data_direction);
 		if (sges_left == 0)
 			return FAILED;
 	} else if (SCpnt->request_bufflen) {
-		SCpnt->SCp.dma_handle = pci_map_single(hd->ioc->pcidev,
+		SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
 				      SCpnt->request_buffer,
 				      SCpnt->request_bufflen,
 				      SCpnt->sc_data_direction);
 		dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
-				hd->ioc->name, SCpnt, SCpnt->request_bufflen));
+				ioc->name, SCpnt, SCpnt->request_bufflen));
 		mptscsih_add_sge((char *) &pReq->SGL,
 			0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
 			SCpnt->SCp.dma_handle);
@@ -493,12 +496,16 @@
 			 * Update the chain element
 			 * Offset and Length fields.
 			 */
-			mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
+			mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
 		} else {
 			/* The current buffer is the original MF
 			 * and there is no Chain buffer.
 			 */
 			pReq->ChainOffset = 0;
+			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
+			dsgprintk((MYIOC_s_ERR_FMT 
+			    "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
+			ioc->RequestNB[req_idx] = RequestNB;
 		}
 	} else {
 		/* At least one chain buffer is needed.
@@ -513,7 +520,7 @@
 		 */
 
 		dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
-				hd->ioc->name, sg_done));
+				ioc->name, sg_done));
 
 		/* Set LAST_ELEMENT flag for last non-chain element
 		 * in the buffer. Since psge points at the NEXT
@@ -537,13 +544,16 @@
 			 */
 			u8 nextChain = (u8) (sgeOffset >> 2);
 			sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
-			mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
+			mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
 		} else {
 			/* The original MF buffer requires a chain buffer -
 			 * set the offset.
 			 * Last element in this MF is a chain element.
 			 */
 			pReq->ChainOffset = (u8) (sgeOffset >> 2);
+			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
+			dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
+			ioc->RequestNB[req_idx] = RequestNB;
 		}
 
 		sges_left -= sg_done;
@@ -552,19 +562,22 @@
 		/* NOTE: psge points to the beginning of the chain element
 		 * in current buffer. Get a chain buffer.
 		 */
-		if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
+		dsgprintk((MYIOC_s_INFO_FMT 
+		    "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",
+		    ioc->name, pReq->CDB[0], SCpnt));
+		if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED)
 			return FAILED;
 
 		/* Update the tracking arrays.
 		 * If chainSge == NULL, update ReqToChain, else ChainToChain
 		 */
 		if (chainSge) {
-			hd->ChainToChain[chain_idx] = newIndex;
+			ioc->ChainToChain[chain_idx] = newIndex;
 		} else {
-			hd->ReqToChain[req_idx] = newIndex;
+			ioc->ReqToChain[req_idx] = newIndex;
 		}
 		chain_idx = newIndex;
-		chain_dma_off = hd->ioc->req_sz * chain_idx;
+		chain_dma_off = ioc->req_sz * chain_idx;
 
 		/* Populate the chainSGE for the current buffer.
 		 * - Set chain buffer pointer to psge and fill
@@ -576,7 +589,7 @@
 
 		/* Start the SGE for the next buffer
 		 */
-		psge = (char *) (hd->ChainBuffer + chain_dma_off);
+		psge = (char *) (ioc->ChainBuffer + chain_dma_off);
 		sgeOffset = 0;
 		sg_done = 0;
 
@@ -631,7 +644,7 @@
 			printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
 			ioc->name);
 
-		mptscsih_freeChainBuffers(hd, req_idx);
+		mptscsih_freeChainBuffers(ioc, req_idx);
 		return 1;
 	}
 
@@ -674,14 +687,15 @@
 
 		status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
 		scsi_state = pScsiReply->SCSIState;
+		scsi_status = pScsiReply->SCSIStatus;
+		xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
 
-		dprintk((KERN_NOTICE "  Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
+		dreplyprintk((KERN_NOTICE " Reply (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
 				ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
 				mf, mr, sc));
-		dprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh"
-				", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
-				status, scsi_state, pScsiReply->SCSIStatus,
-				le32_to_cpu(pScsiReply->IOCLogInfo)));
+		dreplyprintk((KERN_NOTICE "IOCStatus=%04xh SCSIState=%02xh"
+				" SCSIStatus=%02xh xfer_cnt=%08xh\n",
+				status, scsi_state, scsi_status, xfer_cnt));
 
 		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
 			copy_sense_data(sc, hd, mf, pScsiReply);
@@ -701,7 +715,7 @@
 			 * But not: DID_BUS_BUSY lest one risk
 			 * killing interrupt handler:-(
 			 */
-			sc->result = STS_BUSY;
+			sc->result = SAM_STAT_BUSY;
 			break;
 
 		case MPI_IOCSTATUS_SCSI_INVALID_BUS:		/* 0x0041 */
@@ -731,13 +745,22 @@
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
-			sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | 
+			sc->resid = sc->request_bufflen - xfer_cnt;
+			if ( xfer_cnt >= sc->underflow ) {
+				/* Sufficient data transfer occurred */
+				sc->result = (DID_OK << 16) | scsi_status;
+			} else if ( xfer_cnt == 0 ) {
+				/* A CRC Error causes this condition; retry */ 
+				sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | 
 					(CHECK_CONDITION << 1);
-			sc->sense_buffer[0] = 0x70;
-			sc->sense_buffer[2] = NO_SENSE;
-			sc->sense_buffer[12] = 0;
-			sc->sense_buffer[13] = 0;
-			dprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+				sc->sense_buffer[0] = 0x70;
+				sc->sense_buffer[2] = NO_SENSE;
+				sc->sense_buffer[12] = 0;
+				sc->sense_buffer[13] = 0;
+			} else {
+				sc->result = DID_SOFT_ERROR << 16;
+			}
+			dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
 			break;
 		
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
@@ -745,9 +768,7 @@
 			 *  Do upfront check for valid SenseData and give it
 			 *  precedence!
 			 */
-			scsi_status = pScsiReply->SCSIStatus;
 			sc->result = (DID_OK << 16) | scsi_status;
-			xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
 			if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
 				/* Have already saved the status and sense data
 				 */
@@ -769,12 +790,12 @@
 
 			/* Give report and update residual count.
 			 */
-			dprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
+			dreplyprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
 					sc->underflow));
-			dprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
+			dreplyprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
 
 			sc->resid = sc->request_bufflen - xfer_cnt;
-			dprintk((KERN_NOTICE "  SET sc->resid=%02xh\n", sc->resid));
+			dreplyprintk((KERN_NOTICE "  SET sc->resid=%02xh\n", sc->resid));
 			
 			/* Report Queue Full
 			 */
@@ -785,7 +806,8 @@
 
 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
 		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
-			sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
+			scsi_status = pScsiReply->SCSIStatus;
+			sc->result = (DID_OK << 16) | scsi_status;
 			if (scsi_state == 0) {
 				;
 			} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
@@ -851,7 +873,7 @@
 
 		}	/* switch(status) */
 
-		dprintk((KERN_NOTICE "  sc->result set to %08xh\n", sc->result));
+		dreplyprintk((KERN_NOTICE "  sc->result is %08xh\n", sc->result));
 	} /* end of address reply case */
 
 	/* Unmap the DMA buffers, if any. */
@@ -868,88 +890,10 @@
 	sc->scsi_done(sc);		/* Issue the command callback */
 
 	/* Free Chain buffers */
-	mptscsih_freeChainBuffers(hd, req_idx);
+	mptscsih_freeChainBuffers(ioc, req_idx);
 	return 1;
 }
 
-/*
- * Flush all commands on the doneQ.
- * Lock Q when deleting/adding members
- * Lock io_request_lock for OS callback.
- */
-static void
-flush_doneQ(MPT_SCSI_HOST *hd)
-{
-	MPT_DONE_Q	*buffer;
-	struct scsi_cmnd	*SCpnt;
-	unsigned long	 flags;
-
-	/* Flush the doneQ.
-	 */
-	dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n"));
-	while (1) {
-		spin_lock_irqsave(&hd->freedoneQlock, flags);
-		if (Q_IS_EMPTY(&hd->doneQ)) {
-			spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-			break;
-		}
-
-		buffer = hd->doneQ.head;
-		/* Delete from Q
-		 */
-		Q_DEL_ITEM(buffer);
-
-		/* Set the struct scsi_cmnd pointer
-		 */
-		SCpnt = (struct scsi_cmnd *) buffer->argp;
-		buffer->argp = NULL;
-
-		/* Add to the freeQ
-		 */
-		Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-
-		/* Do the OS callback.
-		 */
-		SCpnt->scsi_done(SCpnt);
-	}
-
-	return;
-}
-
-/*
- * Search the doneQ for a specific command. If found, delete from Q.
- * Calling function will finish processing.
- */
-static void
-search_doneQ_for_cmd(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt)
-{
-	unsigned long	 flags;
-	MPT_DONE_Q	*buffer;
-
-	spin_lock_irqsave(&hd->freedoneQlock, flags);
-	if (!Q_IS_EMPTY(&hd->doneQ)) {
-		buffer = hd->doneQ.head;
-		do {
-			struct scsi_cmnd *sc = (struct scsi_cmnd *) buffer->argp;
-			if (SCpnt == sc) {
-				Q_DEL_ITEM(buffer);
-				SCpnt->result = sc->result;
-
-				/* Set the struct scsi_cmnd pointer
-				 */
-				buffer->argp = NULL;
-
-				/* Add to the freeQ
-				 */
-				Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-				break;
-			}
-		} while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
-	}
-	spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-	return;
-}
 
 /*
  *	mptscsih_flush_running_cmds - For each command found, search
@@ -964,12 +908,11 @@
 static void
 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 {
+	MPT_ADAPTER *ioc = hd->ioc;
 	struct scsi_cmnd	*SCpnt;
 	MPT_FRAME_HDR	*mf;
-	MPT_DONE_Q	*buffer;
 	int		 ii;
-	int		 max = hd->ioc->req_depth;
-	unsigned long	 flags;
+	int		 max = ioc->req_depth;
 
 	dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
 	for (ii= 0; ii < max; ii++) {
@@ -978,16 +921,11 @@
 			/* Command found.
 			 */
 
-			/* Search pendingQ, if found,
-			 * delete from Q.
-			 */
-			mptscsih_search_pendingQ(hd, ii);
-
 			/* Null ScsiLookup index
 			 */
 			hd->ScsiLookup[ii] = NULL;
 
-			mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
+			mf = MPT_INDEX_2_MFPTR(ioc, ii);
 			dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
 					mf, SCpnt));
 
@@ -997,12 +935,12 @@
 			 */
 			if (scsi_device_online(SCpnt->device)) {
 				if (SCpnt->use_sg) {
-					pci_unmap_sg(hd->ioc->pcidev,
+					pci_unmap_sg(ioc->pcidev,
 						(struct scatterlist *) SCpnt->request_buffer,
 						SCpnt->use_sg,
 						SCpnt->sc_data_direction);
 				} else if (SCpnt->request_bufflen) {
-					pci_unmap_single(hd->ioc->pcidev,
+					pci_unmap_single(ioc->pcidev,
 						SCpnt->SCp.dma_handle,
 						SCpnt->request_bufflen,
 						SCpnt->sc_data_direction);
@@ -1012,37 +950,12 @@
 			SCpnt->host_scribble = NULL;
 
 			/* Free Chain buffers */
-			mptscsih_freeChainBuffers(hd, ii);
+			mptscsih_freeChainBuffers(ioc, ii);
 
 			/* Free Message frames */
-			mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf);
-
-#if 1
-			/* Post to doneQ, do not reply until POST phase
-			 * of reset handler....prevents new commands from
-			 * being queued.
-			 */
-			spin_lock_irqsave(&hd->freedoneQlock, flags);
-			if (!Q_IS_EMPTY(&hd->freeQ)) {
-				buffer = hd->freeQ.head;
-				Q_DEL_ITEM(buffer);
-
-				/* Set the struct scsi_cmnd pointer
-				 */
-				buffer->argp = (void *)SCpnt;
+			mpt_free_msg_frame(ioc, mf);
 
-				/* Add to the doneQ
-				 */
-				Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
-				spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-			} else {
-				spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-				SCpnt->scsi_done(SCpnt);
-			}
-#else
 			SCpnt->scsi_done(SCpnt);	/* Issue the command callback */
-#endif
-
 		}
 	}
 
@@ -1087,8 +1000,8 @@
 			/* Cleanup
 			 */
 			hd->ScsiLookup[ii] = NULL;
-			mptscsih_freeChainBuffers(hd, ii);
-			mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, (MPT_FRAME_HDR *)mf);
+			mptscsih_freeChainBuffers(hd->ioc, ii);
+			mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
 		}
 	}
 
@@ -1097,111 +1010,6 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptscsih_initChainBuffers - Allocate memory for and initialize
- *	chain buffers, chain buffer control arrays and spinlock.
- *	@hd: Pointer to MPT_SCSI_HOST structure
- *	@init: If set, initialize the spin lock.
- */
-static int
-mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
-{
-	MPT_FRAME_HDR	*chain;
-	u8		*mem;
-	unsigned long	flags;
-	int		sz, ii, num_chain;
-	int 		scale, num_sge;
-
-	/* chain buffer allocation done from PrimeIocFifos */	
-	if (hd->ioc->fifo_pool == NULL) 
-		return -1;
-	
-	hd->ChainBuffer = hd->ioc->chain_alloc;
-	hd->ChainBufferDMA = hd->ioc->chain_alloc_dma;
-	
-	dprintk((KERN_INFO "  ChainBuffer    @ %p(%p), sz=%d\n",
-		 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz));
-		
-	/* ReqToChain size must equal the req_depth
-	 * index = req_idx
-	 */
-	if (hd->ReqToChain == NULL) {
-		sz = hd->ioc->req_depth * sizeof(int);
-		mem = kmalloc(sz, GFP_ATOMIC);
-		if (mem == NULL)
-			return -1;
-
-		hd->ReqToChain = (int *) mem;
-	}
-	for (ii = 0; ii < hd->ioc->req_depth; ii++)
-		hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
-
-	/* ChainToChain size must equal the total number
-	 * of chain buffers to be allocated.
-	 * index = chain_idx
-	 *
-	 * Calculate the number of chain buffers needed(plus 1) per I/O
-	 * then multiply the the maximum number of simultaneous cmds
-	 *
-	 * num_sge = num sge in request frame + last chain buffer
-	 * scale = num sge per chain buffer if no chain element
-	 */
-	scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-	if (sizeof(dma_addr_t) == sizeof(u64))
-		num_sge =  scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
-	else
-		num_sge =  1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
-
-	num_chain = 1;
-	while (hd->max_sge - num_sge > 0) {
-		num_chain++;
-		num_sge += (scale - 1);
-	}
-	num_chain++;
-
-	if ((int) hd->ioc->chip_type > (int) FC929)
-		num_chain *= MPT_SCSI_CAN_QUEUE;
-	else
-		num_chain *= MPT_FC_CAN_QUEUE;
-
-	hd->num_chain = num_chain;
-
-	sz = num_chain * sizeof(int);
-	if (hd->ChainToChain == NULL) {
-		mem = kmalloc(sz, GFP_ATOMIC);
-		if (mem == NULL)
-			return -1;
-
-		hd->ChainToChain = (int *) mem;
-	} else {
-		mem = (u8 *) hd->ChainToChain;
-	}
-	memset(mem, 0xFF, sz);
-
-
-	/* Initialize the free chain Q.
-	 */
-	if (init) {
-		spin_lock_init(&hd->FreeChainQlock);
-	}
-
-	spin_lock_irqsave (&hd->FreeChainQlock, flags);
-	Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
-
-	/* Post the chain buffers to the FreeChainQ.
-	 */
-	mem = (u8 *)hd->ChainBuffer;
-	for (ii=0; ii < num_chain; ii++) {
-		chain = (MPT_FRAME_HDR *) mem;
-		Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
-		mem += hd->ioc->req_sz;
-	}
-	spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
-
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
  *  Hack! It might be nice to report if a device is returning QUEUE_FULL
  *  but maybe not each and every time...
  */
@@ -1254,7 +1062,6 @@
 	struct Scsi_Host	*sh;
 	MPT_SCSI_HOST		*hd;
 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
-	MPT_DONE_Q		*freedoneQ;
 	unsigned long		 flags;
 	int			 sz, ii;
 	int			 numSGE = 0;
@@ -1386,7 +1193,6 @@
 
 	hd = (MPT_SCSI_HOST *) sh->hostdata;
 	hd->ioc = ioc;
-	hd->max_sge = sh->sg_tablesize;
 
 	if ((int)ioc->chip_type > (int)FC929)
 	hd->is_spi = 1;
@@ -1399,7 +1205,7 @@
 	/* SCSI needs scsi_cmnd lookup table!
 	 * (with size equal to req_depth*PtrSz!)
 	 */
-	sz = hd->ioc->req_depth * sizeof(void *);
+	sz = ioc->req_depth * sizeof(void *);
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
@@ -1412,37 +1218,6 @@
 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
 		 ioc->name, hd->ScsiLookup, sz));
 		
-	if (mptscsih_initChainBuffers(hd, 1) < 0) {
-		error = -EINVAL;
-		goto mptscsih_probe_failed;
-	}
-
-	/* Allocate memory for free and doneQ's
-	 */
-	sz = sh->can_queue * sizeof(MPT_DONE_Q);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
-		error = -ENOMEM;
-		goto mptscsih_probe_failed;
-	}
-
-	memset(mem, 0xFF, sz);
-	hd->memQ = mem;
-
-	/* Initialize the free, done and pending Qs.
-	 */
-	Q_INIT(&hd->freeQ, MPT_DONE_Q);
-	Q_INIT(&hd->doneQ, MPT_DONE_Q);
-	Q_INIT(&hd->pendingQ, MPT_DONE_Q);
-	spin_lock_init(&hd->freedoneQlock);
-
-	mem = hd->memQ;
-	for (ii=0; ii < sh->can_queue; ii++) {
-		freedoneQ = (MPT_DONE_Q *) mem;
-		Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
-		mem += sizeof(MPT_DONE_Q);
-	}
-
 	/* Initialize this Scsi_Host
 	 * internal task Q.
 	 */
@@ -1474,8 +1249,7 @@
 	hd->resetPending = 0;
 	hd->abortSCpnt = NULL;
 	hd->tmPtr = NULL;
-	hd->numTMrequests = 0;
-		
+
 	/* Clear the pointer used to store
 	 * single-threaded commands, i.e., those
 	 * issued during a bus scan, dv and
@@ -1500,10 +1274,10 @@
 	/* ioc->sh = sh;	*/
 
 #ifdef MPTSCSIH_DBG_TIMEOUT
-	hd->ioc->timeout_hard = 0;
-	hd->ioc->timeout_delta = 30 * HZ;
-	hd->ioc->timeout_maxcnt = 0;
-	hd->ioc->timeout_cnt = 0;
+	ioc->timeout_hard = 0;
+	ioc->timeout_delta = 30 * HZ;
+	ioc->timeout_maxcnt = 0;
+	ioc->timeout_cnt = 0;
 	for (ii=0; ii < 8; ii++)
 		foo_to[ii] = NULL;
 #endif
@@ -1511,47 +1285,41 @@
 		/* Update with the driver setup
 		 * values.
 		 */
-		if (hd->ioc->spi_data.maxBusWidth >
+		if (ioc->spi_data.maxBusWidth >
 		  driver_setup.max_width) {
-			hd->ioc->spi_data.maxBusWidth =
+			ioc->spi_data.maxBusWidth =
 			  driver_setup.max_width;
 		}
 
-		if (hd->ioc->spi_data.minSyncFactor <
+		if (ioc->spi_data.minSyncFactor <
 		  driver_setup.min_sync_fac) {
-			hd->ioc->spi_data.minSyncFactor =
+			ioc->spi_data.minSyncFactor =
 			  driver_setup.min_sync_fac;
 		}
 
-		if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) {
-			hd->ioc->spi_data.maxSyncOffset = 0;
+		if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
+			ioc->spi_data.maxSyncOffset = 0;
 		}
 
-		hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
+		ioc->spi_data.Saf_Te = driver_setup.saf_te;
 
 		hd->negoNvram = 0;
 #ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 		hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
 #endif
-		if (driver_setup.dv == 0) {
-			hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
-		}
-
-		hd->ioc->spi_data.forceDv = 0;
+		ioc->spi_data.forceDv = 0;
 		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-			hd->ioc->spi_data.dvStatus[ii] =
+			ioc->spi_data.dvStatus[ii] =
 			  MPT_SCSICFG_NEGOTIATE;
 		}
 
-		if (hd->negoNvram == 0) {
-			for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
-				hd->ioc->spi_data.dvStatus[ii] |=
-				  MPT_SCSICFG_DV_NOT_DONE;
-		}
+		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+			ioc->spi_data.dvStatus[ii] |=
+			  MPT_SCSICFG_DV_NOT_DONE;
 
 		ddvprintk((MYIOC_s_INFO_FMT
 			"dv %x width %x factor %x saf_te %x\n",
-			hd->ioc->name, driver_setup.dv,
+			ioc->name, driver_setup.dv,
 			driver_setup.max_width,
 			driver_setup.min_sync_fac,
 			driver_setup.saf_te));
@@ -1620,14 +1388,11 @@
 
 	hd = (MPT_SCSI_HOST *)host->hostdata;
 	if (hd != NULL) {
-		int sz1, sz2, sz3, sztarget=0;
-		int szr2chain = 0;
-		int szc2chain = 0;
-		int szQ = 0;
+		int sz1, sz3, sztarget=0;
 
 		mptscsih_shutdown(&pdev->dev);
 
-		sz1 = sz2 = sz3 = 0;
+		sz1 = sz3 = 0;
 
 		if (hd->ScsiLookup != NULL) {
 			sz1 = hd->ioc->req_depth * sizeof(void *);
@@ -1635,24 +1400,6 @@
 			hd->ScsiLookup = NULL;
 		}
 
-		if (hd->ReqToChain != NULL) {
-			szr2chain = hd->ioc->req_depth * sizeof(int);
-			kfree(hd->ReqToChain);
-			hd->ReqToChain = NULL;
-		}
-
-		if (hd->ChainToChain != NULL) {
-			szc2chain = hd->num_chain * sizeof(int);
-			kfree(hd->ChainToChain);
-			hd->ChainToChain = NULL;
-		}
-
-		if (hd->memQ != NULL) {
-			szQ = host->can_queue * sizeof(MPT_DONE_Q);
-			kfree(hd->memQ);
-			hd->memQ = NULL;
-		}
-
 		if (hd->Targets != NULL) {
 			int max, ii;
 
@@ -1680,9 +1427,9 @@
 			hd->Targets = NULL;
 		}
 
-		dprintk((MYIOC_s_INFO_FMT
-		  "Free'd ScsiLookup (%d) Target (%d+%d) memory\n",
-		  hd->ioc->name, sz1, sz3, sztarget));
+		dprintk((MYIOC_s_INFO_FMT 
+		    "Free'd ScsiLookup (%d) Target (%d+%d) memory\n",
+		    hd->ioc->name, sz1, sz3, sztarget));
 		dprintk(("Free'd done and free Q (%d) memory\n", szQ));
 
 		/* NULL the Scsi_Host pointer
@@ -1802,7 +1549,7 @@
 	ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
 
 	if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
-		dprintk((KERN_INFO MYNAM
+		devtprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
 
@@ -1864,7 +1611,7 @@
  *
  *	Returns pointer to buffer where information was written.
  */
-const char *
+static const char *
 mptscsih_info(struct Scsi_Host *SChost)
 {
 	MPT_SCSI_HOST *h;
@@ -2079,7 +1826,8 @@
  * 	hostno: scsi host number
  *	func:   if write = 1; if read = 0
  */
-int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
+static int 
+mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
 			int length, int func)
 {
 	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)host->hostdata;
@@ -2114,15 +1862,13 @@
  *
  *	Returns 0. (rtn value discarded by linux scsi mid-layer)
  */
-int
+static int
 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
 	MPT_SCSI_HOST		*hd;
 	MPT_FRAME_HDR		*mf;
 	SCSIIORequest_t		*pScsiReq;
 	VirtDevice		*pTarget;
-	MPT_DONE_Q		*buffer;
-	unsigned long		 flags;
 	int	 target;
 	int	 lun;
 	u32	 datalen;
@@ -2147,16 +1893,9 @@
 			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
 
 	if (hd->resetPending) {
-		/* Prevent new commands from being issued
-		 * while reloading the FW. Reset timer to 60 seconds,
-		 * as the FW can take some time to come ready.
-		 * For New EH, cmds on doneQ posted to FW.
-		 */
-		did_errcode = 1;
-		mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
 		dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
 			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
-		goto did_error;
+		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
 	/*
@@ -2165,8 +1904,7 @@
 	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc)) == NULL) {
 		dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
 				hd->ioc->name));
-		did_errcode = 2;
-		goto did_error;
+		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
 	pScsiReq = (SCSIIORequest_t *) mf;
@@ -2249,7 +1987,7 @@
 			(dma_addr_t) -1);
 	} else {
 		/* Add a 32 or 64 bit SGE */
-		rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
+		rc = mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx);
 	}
 
 
@@ -2283,7 +2021,7 @@
 				}
 
 				/* Trying to do DV to this target, extend timeout.
-				 * Wait to issue intil flag is clear
+				 * Wait to issue until flag is clear
 				 */
 				if (dvStatus & MPT_SCSICFG_DV_PENDING) {
 					mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
@@ -2314,64 +2052,18 @@
 			mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
 			dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
 					hd->ioc->name, SCpnt, mf, my_idx));
-		} else {
-			ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
-					hd->ioc->name, SCpnt, my_idx));
-			/* Place this command on the pendingQ if possible */
-			spin_lock_irqsave(&hd->freedoneQlock, flags);
-			if (!Q_IS_EMPTY(&hd->freeQ)) {
-				buffer = hd->freeQ.head;
-				Q_DEL_ITEM(buffer);
-
-				/* Save the mf pointer
-				 */
-				buffer->argp = (void *)mf;
-
-				/* Add to the pendingQ
-				 */
-				Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
-				spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-			} else {
-				spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-				SCpnt->result = (DID_BUS_BUSY << 16);
-				SCpnt->scsi_done(SCpnt);
-			}
-		}
-	} else {
-		mptscsih_freeChainBuffers(hd, my_idx);
-		mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf);
-		did_errcode = 3;
-		goto did_error;
-	}
+			DBG_DUMP_REQUEST_FRAME(mf)
+		} else
+			goto fail;
+	} else
+		goto fail;
 
 	return 0;
 
-did_error:
-	dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",
-			hd->ioc->name, did_errcode, SCpnt));
-	/* Just wish OS to issue a retry */
-	SCpnt->result = (DID_BUS_BUSY << 16);
-	spin_lock_irqsave(&hd->freedoneQlock, flags);
-	if (!Q_IS_EMPTY(&hd->freeQ)) {
-		dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",
-			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
-		buffer = hd->freeQ.head;
-		Q_DEL_ITEM(buffer);
-
-		/* Set the scsi_cmnd pointer
-		 */
-		buffer->argp = (void *)SCpnt;
-
-		/* Add to the doneQ
-		 */
-		Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-	} else {
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-		SCpnt->scsi_done(SCpnt);
-	}
-
-	return 0;
+ fail:
+	mptscsih_freeChainBuffers(hd->ioc, my_idx);
+	mpt_free_msg_frame(hd->ioc, mf);
+	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2385,7 +2077,7 @@
  *	No return.
  */
 static void
-mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
+mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
 {
 	MPT_FRAME_HDR *chain;
 	unsigned long flags;
@@ -2395,28 +2087,28 @@
 	/* Get the first chain index and reset
 	 * tracker state.
 	 */
-	chain_idx = hd->ReqToChain[req_idx];
-	hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
+	chain_idx = ioc->ReqToChain[req_idx];
+	ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
 
 	while (chain_idx != MPT_HOST_NO_CHAIN) {
 
 		/* Save the next chain buffer index */
-		next = hd->ChainToChain[chain_idx];
+		next = ioc->ChainToChain[chain_idx];
 
 		/* Free this chain buffer and reset
 		 * tracker
 		 */
-		hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
+		ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
 
-		chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
-					+ (chain_idx * hd->ioc->req_sz));
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-		Q_ADD_TAIL(&hd->FreeChainQ.head,
+		chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
+					+ (chain_idx * ioc->req_sz));
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
+		Q_ADD_TAIL(&ioc->FreeChainQ.head,
 					&chain->u.frame.linkage, MPT_FRAME_HDR);
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 		dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
-				hd->ioc->name, chain_idx));
+				ioc->name, chain_idx));
 
 		/* handle next */
 		chain_idx = next;
@@ -2480,12 +2172,6 @@
 	}
 	spin_unlock_irqrestore(&ioc->diagLock, flags);
 
-	/* Do not do a Task Management if there are
-	 * too many failed TMs on this adapter.
-	 */
-	if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
-		doTask = 0;
-
 	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
 	 *  If we time out and not bus reset, then we return a FAILED status to the caller.
 	 *  The call to mptscsih_tm_pending_wait() will set the pending flag if we are
@@ -2593,7 +2279,7 @@
 	/* Return Fail to calling function if no message frames available.
 	 */
 	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc)) == NULL) {
-		dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
+		dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
 				hd->ioc->name));
 		//return FAILED;
 		return -999;
@@ -2624,29 +2310,30 @@
 		pScsiTm->Reserved2[ii] = 0;
 
 	pScsiTm->TaskMsgContext = ctx2abort;
-	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n",
-			hd->ioc->name, ctx2abort, type));
 
 	/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
 		mpt_put_msg_frame(hd->ioc->id, mf);
 	* Save the MF pointer in case the request times out.
 	*/
 	hd->tmPtr = mf;
-	hd->numTMrequests++;
 	hd->TMtimer.expires = jiffies + timeout;
 	add_timer(&hd->TMtimer);
 
+	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+			hd->ioc->name, ctx2abort, type));
+
+	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
+
 	if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc,
 				sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
 	!= 0) {
-		dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
+		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
 			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
-		hd->numTMrequests--;
 		hd->tmPtr = NULL;
 		del_timer(&hd->TMtimer);
-		mpt_free_msg_frame(ScsiTaskCtx, hd->ioc, mf);
+		mpt_free_msg_frame(hd->ioc, mf);
 	}
-
+	
 	return retval;
 }
 
@@ -2659,10 +2346,11 @@
  *
  *	Returns SUCCESS or FAILED.
  */
-int
+static int
 mptscsih_abort(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
+	MPT_ADAPTER	*ioc;
 	MPT_FRAME_HDR	*mf;
 	u32		 ctx2abort;
 	int		 scpnt_idx;
@@ -2673,12 +2361,13 @@
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
 		SCpnt->result = DID_RESET << 16;
 		SCpnt->scsi_done(SCpnt);
-		dtmprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
+		dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
 			   "Can't locate host! (sc=%p)\n",
 			   SCpnt));
 		return FAILED;
 	}
 
+	ioc = hd->ioc;
 	if (hd->resetPending)
 		return FAILED;
 
@@ -2691,11 +2380,9 @@
 	/* Find this command
 	 */
 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
-		/* Cmd not found in ScsiLookup. If found in
-		 * doneQ, delete from Q. Do OS callback.
+		/* Cmd not found in ScsiLookup. 
+		 * Do OS callback.
 		 */
-		search_doneQ_for_cmd(hd, SCpnt);
-
 		SCpnt->result = DID_RESET << 16;
 		dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
 			   "Command not in the active list! (sc=%p)\n",
@@ -2703,18 +2390,6 @@
 		return SUCCESS;
 	}
 
-	/* If this command is pended, then timeout/hang occurred
-	 * during DV. Post command and flush pending Q
-	 * and then following up with the reset request.
-	 */
-	if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-		mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
-		post_pendingQ_commands(hd);
-		dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
-			   "Posting pended cmd! (sc=%p)\n",
-			   hd->ioc->name, SCpnt));
-	}
-
 	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
 	 * (the IO to be ABORT'd)
 	 *
@@ -2724,7 +2399,7 @@
 	 */
 	mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
 	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
-
+	
 	hd->abortSCpnt = SCpnt;
 
 	spin_unlock_irq(host_lock);
@@ -2743,12 +2418,26 @@
 		 */
 		hd->tmPending = 0;
 		hd->tmState = TM_STATE_NONE;
-
+		
 		spin_lock_irq(host_lock);
+
+		/* Unmap the DMA buffers, if any. */
+		if (SCpnt->use_sg) {
+			pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
+				    SCpnt->use_sg, SCpnt->sc_data_direction);
+		} else if (SCpnt->request_bufflen) {
+			pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle,
+				SCpnt->request_bufflen, SCpnt->sc_data_direction);
+		}
+		hd->ScsiLookup[scpnt_idx] = NULL;
+		SCpnt->result = DID_RESET << 16;
+		SCpnt->scsi_done(SCpnt);		/* Issue the command callback */
+		mptscsih_freeChainBuffers(ioc, scpnt_idx);
+		mpt_free_msg_frame(ioc, mf);
 		return FAILED;
 	}
 	spin_lock_irq(host_lock);
-	return FAILED;
+	return SUCCESS;
 
 }
 
@@ -2761,7 +2450,7 @@
  *
  *	Returns SUCCESS or FAILED.
  */
-int
+static int
 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
@@ -2816,7 +2505,7 @@
  *
  *	Returns SUCCESS or FAILED.
  */
-int
+static int
 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
@@ -2839,9 +2528,6 @@
 
 	/* We are now ready to execute the task management request. */
 	spin_unlock_irq(host_lock);
-//	printk("testing start : mptscsih_schedule_reset\n");
-//	mptscsih_schedule_reset(hd);
-//	printk("testing end: mptscsih_schedule_reset\n");
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
 		SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
 	    < 0){
@@ -2871,7 +2557,7 @@
  *
  *	Returns SUCCESS or FAILED.
  */
-int
+static int
 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
 {
 	MPT_SCSI_HOST *  hd;
@@ -2965,9 +2651,10 @@
 	SCSITaskMgmt_t		*pScsiTmReq;
 	MPT_SCSI_HOST		*hd;
 	unsigned long		 flags;
-	u8			 tmType = 0;
+	u16			 iocstatus;
+	u8			 tmType;
 
-	dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
+	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
 			ioc->name, mf, mr));
 	if (ioc->sh) {
 		/* Depending on the thread, a timer is activated for
@@ -2978,7 +2665,7 @@
 		if (hd->tmPtr) {
 			del_timer(&hd->TMtimer);
 		}
-		dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
+		dtmprintk((MYIOC_s_WARN_FMT "taskQcnt (%d)\n",
 			ioc->name, hd->taskQcnt));
 	} else {
 		dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
@@ -2997,18 +2684,15 @@
 		/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
 		tmType = pScsiTmReq->TaskType;
 
-		dtmprintk((KERN_INFO "  TaskType = %d, TerminationCount=%d\n",
-				tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
-
+		dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
+				ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
+		DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
+
+		iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+		dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
+			ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
 		/* Error?  (anything non-zero?) */
-		if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
-			u16	 iocstatus;
-
-			iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-			dtmprintk((KERN_INFO "  SCSI TaskMgmt (%d) - Oops!\n", tmType));
-			dtmprintk((KERN_INFO "  IOCStatus = %04xh\n", iocstatus));
-			dtmprintk((KERN_INFO "  IOCLogInfo = %08xh\n",
-				 le32_to_cpu(pScsiTmReply->IOCLogInfo)));
+		if (iocstatus) {
 
 			/* clear flags and continue.
 			 */
@@ -3029,11 +2713,9 @@
 				}
 			}
 		} else {
-			dtmprintk((KERN_INFO "  SCSI TaskMgmt SUCCESS!\n"));
+			dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
 
-			hd->numTMrequests--;
 			hd->abortSCpnt = NULL;
-			flush_doneQ(hd);
 
 		}
 	}
@@ -3051,26 +2733,21 @@
 /*
  *	This is anyones guess quite frankly.
  */
-int
+static int
 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
 		sector_t capacity, int geom[])
 {
 	int		heads;
 	int		sectors;
 	sector_t	cylinders;
-#ifdef CONFIG_LBD
 	ulong 		dummy;
-#endif
 
 	heads = 64;
 	sectors = 32;
-#ifdef CONFIG_LBD
+
 	dummy = heads * sectors;
 	cylinders = capacity;
 	sector_div(cylinders,dummy);
-#else
-	cylinders = (ulong)capacity / (heads * sectors);
-#endif
 
 	/*
 	 * Handle extended translation size for logical drives
@@ -3079,13 +2756,9 @@
 	if ((ulong)capacity >= 0x200000) {
 		heads = 255;
 		sectors = 63;
-#ifdef CONFIG_LBD
 		dummy = heads * sectors;
 		cylinders = capacity;
 		sector_div(cylinders,dummy);
-#else
-		cylinders = (ulong)capacity / (heads * sectors);
-#endif
 	}
 
 	/* return result */
@@ -3107,7 +2780,7 @@
  *	Return non-zero if allocation fails.
  *	Init memory once per id (not LUN).
  */
-int
+static int
 mptscsih_slave_alloc(struct scsi_device *device)
 {
 	struct Scsi_Host	*host = device->host;
@@ -3130,12 +2803,21 @@
 			Q_INIT(&vdev->WaitQ, void);
 			Q_INIT(&vdev->SentQ, void);
 			Q_INIT(&vdev->DoneQ, void);
-			vdev->tflags = 0;
+			vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
 			vdev->ioc_id = hd->ioc->id;
 			vdev->target_id = device->id;
-			vdev->bus_id = hd->port;
-
+			vdev->bus_id = device->channel;
+			vdev->raidVolume = 0;
 			hd->Targets[device->id] = vdev;
+			if (hd->is_spi) {
+				if (hd->ioc->spi_data.isRaid & (1 << device->id)) {
+					vdev->raidVolume = 1;
+					ddvtprintk((KERN_INFO
+					    "RAID Volume @ id %d\n", device->id));
+				}
+			} else {
+				vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+			}
 		}
 	}
 	vdev->num_luns++;
@@ -3147,7 +2829,7 @@
  *	OS entry point to allow for host driver to free allocated memory
  *	Called if no device present or device being unloaded
  */
-void
+static void
 mptscsih_slave_destroy(struct scsi_device *device)
 {
 	struct Scsi_Host	*host = device->host;
@@ -3176,15 +2858,15 @@
 			kfree(hd->Targets[device->id]);
 			hd->Targets[device->id] = NULL;
 
-			if (!hd->is_spi) 
+			if (!hd->is_spi)
 				return;
 
 			if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) {
 			int i;
 				for(i=0;i<hd->ioc->spi_data.pIocPg3->NumPhysDisks &&
 					raid_volume==0;i++)
-						
-					if(device->id == 
+
+					if(device->id ==
 					  hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) {
 						raid_volume=1;
 						hd->ioc->spi_data.forceDv |=
@@ -3202,7 +2884,7 @@
 			}
 		}
 	}
-	
+
 	return;
 }
 
@@ -3212,7 +2894,7 @@
  *	member to 1 if a device does not support Q tags.
  *	Return non-zero if fails.
  */
-int
+static int
 mptscsih_slave_configure(struct scsi_device *device)
 {
 	struct Scsi_Host	*sh = device->host;
@@ -3240,8 +2922,16 @@
 	pTarget = hd->Targets[device->id];
 
 	if (pTarget == NULL) {
-		/* error case - don't know about this device */
-		scsi_adjust_queue_depth(device, 0, 1);
+		/* Driver doesn't know about this device.
+		 * Kernel may generate a "Dummy Lun 0" which
+		 * may become a real Lun if a 
+		 * "scsi add-single-device" command is executed
+		 * while the driver is active (hot-plug a 
+		 * device).  LSI Raid controllers need 
+		 * queue_depth set to DEV_HIGH for this reason.
+		 */
+		scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
+			MPT_SCSI_CMD_PER_DEV_HIGH);
 		goto slave_configure_exit;
 	}
 
@@ -3302,8 +2992,6 @@
 	SCSIIORequest_t	*pReq;
 	u32		 sense_count = le32_to_cpu(pScsiReply->SenseCount);
 	int		 index;
-	char		 devFoo[96];
-	IO_Info_t	 thisIo;
 
 	/* Get target structure
 	 */
@@ -3342,35 +3030,10 @@
 				ioc->eventContext++;
 			}
 		}
-
-		/* Print an error report for the user.
-		 */
-		thisIo.cdbPtr = sc->cmnd;
-		thisIo.sensePtr = sc->sense_buffer;
-		thisIo.SCSIStatus = pScsiReply->SCSIStatus;
-		thisIo.DoDisplay = 1;
-		if (hd->is_multipath)
-			sprintf(devFoo, "%d:%d:%d",
-					hd->ioc->id,
-					pReq->TargetID,
-					pReq->LUN[1]);
-		else
-			sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun);
-		thisIo.DevIDStr = devFoo;
-/* fubar */
-		thisIo.dataPtr = NULL;
-		thisIo.inqPtr = NULL;
-		if (sc->device) {
-			thisIo.inqPtr = sc->device->vendor-8;	/* FIXME!!! */
-		}
-		(void) mpt_ScsiHost_ErrorReport(&thisIo);
-
 	} else {
 		dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
 				hd->ioc->name));
 	}
-
-	return;
 }
 
 static u32
@@ -3390,102 +3053,6 @@
 	return -1;
 }
 
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Search the pendingQ for a command with specific index.
- * If found, delete and return mf pointer
- * If not found, return NULL
- */
-static MPT_FRAME_HDR *
-mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx)
-{
-	unsigned long	 flags;
-	MPT_DONE_Q	*buffer;
-	MPT_FRAME_HDR	*mf = NULL;
-	MPT_FRAME_HDR	*cmdMfPtr;
-
-	ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
-	cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
-	spin_lock_irqsave(&hd->freedoneQlock, flags);
-	if (!Q_IS_EMPTY(&hd->pendingQ)) {
-		buffer = hd->pendingQ.head;
-		do {
-			mf = (MPT_FRAME_HDR *) buffer->argp;
-			if (mf == cmdMfPtr) {
-				Q_DEL_ITEM(buffer);
-
-				/* clear the arg pointer
-				 */
-				buffer->argp = NULL;
-
-				/* Add to the freeQ
-				 */
-				Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-				break;
-			}
-			mf = NULL;
-		} while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ);
-	}
-	spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-	ddvtprintk((" ...return %p\n", mf));
-	return mf;
-}
-
-/* Post all commands on the pendingQ to the FW.
- * Lock Q when deleting/adding members
- * Lock io_request_lock for OS callback.
- */
-static void
-post_pendingQ_commands(MPT_SCSI_HOST *hd)
-{
-	MPT_FRAME_HDR	*mf;
-	MPT_DONE_Q	*buffer;
-	unsigned long	 flags;
-
-	/* Flush the pendingQ.
-	 */
-	ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
-	while (1) {
-		spin_lock_irqsave(&hd->freedoneQlock, flags);
-		if (Q_IS_EMPTY(&hd->pendingQ)) {
-			spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-			break;
-		}
-
-		buffer = hd->pendingQ.head;
-		/* Delete from Q
-		 */
-		Q_DEL_ITEM(buffer);
-
-		mf = (MPT_FRAME_HDR *) buffer->argp;
-		buffer->argp = NULL;
-
-		/* Add to the freeQ
-		 */
-		Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-
-		if (!mf) {
-			/* This should never happen */
-			printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
-			continue;
-		}
-
-		mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
-
-#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
-		{
-			u16		 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-			struct scsi_cmnd	*sc = hd->ScsiLookup[req_idx];
-			printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
-					hd->ioc->name, sc, req_idx, mf);
-		}
-#endif
-	}
-
-	return;
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
@@ -3520,14 +3087,10 @@
 		dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
 
 		/* 2. Flush running commands
-		 *	Clean drop test code - if compiled
 		 *	Clean ScsiLookup (and associated memory)
 		 *	AND clean mytaskQ
 		 */
 
-		/* 2a. Drop Test Command.
-		 */
-
 		/* 2b. Reply to OS all known outstanding I/O commands.
 		 */
 		mptscsih_flush_running_cmds(hd);
@@ -3538,7 +3101,7 @@
 		 */
 		if (hd->cmdPtr) {
 			del_timer(&hd->timer);
-			mpt_free_msg_frame(ScsiScanDvCtx, ioc, hd->cmdPtr);
+			mpt_free_msg_frame(ioc, hd->cmdPtr);
 		}
 
 		/* 2d. If a task management has not completed,
@@ -3546,7 +3109,7 @@
 		 */
 		if (hd->tmPtr) {
 			del_timer(&hd->TMtimer);
-			mpt_free_msg_frame(ScsiTaskCtx, ioc, hd->tmPtr);
+			mpt_free_msg_frame(ioc, hd->tmPtr);
 		}
 
 #ifdef MPTSCSIH_DBG_TIMEOUT
@@ -3573,7 +3136,6 @@
 
 		/* 2. Chain Buffer initialization
 		 */
-		mptscsih_initChainBuffers(hd, 0);
 
 		/* 3. tmPtr clear
 		 */
@@ -3583,8 +3145,10 @@
 
 		/* 4. Renegotiate to all devices, if SCSI
 		 */
-		if (hd->is_spi)
+		if (hd->is_spi) {
+			dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
 			mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
+		}
 
 		/* 5. Enable new commands to be posted
 		 */
@@ -3592,7 +3156,6 @@
 		hd->tmPending = 0;
 		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 		hd->resetPending = 0;
-		hd->numTMrequests = 0;
 		hd->tmState = TM_STATE_NONE;
 
 		/* 6. If there was an internal command,
@@ -3609,11 +3172,7 @@
 			hd->cmdPtr = NULL;
 		}
 
-		/* 7. Flush doneQ
-		 */
-		flush_doneQ(hd);
-
-		/* 8. Set flag to force DV and re-read IOC Page 3
+		/* 7. Set flag to force DV and re-read IOC Page 3
 		 */
 		if (hd->is_spi) {
 			ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
@@ -3634,7 +3193,7 @@
 	MPT_SCSI_HOST *hd;
 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
 
-	dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
+	devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
 			ioc->name, event));
 
 	switch (event) {
@@ -3766,394 +3325,6 @@
 	.use_clustering			= ENABLE_CLUSTERING,
 };
 
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Private data...
- */
-static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* old symsense.c stuff... */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * Private data...
- * To protect ourselves against those that would pass us bogus pointers
- */
-static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
-    = { 0x1F, 0x00, 0x00, 0x00,
-	0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
-    = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00 };
-static u8 dummyCDB[16]
-    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static u8 dummyScsiData[16]
-    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-static char *ScsiStatusString[] = {
-	"GOOD",					/* 00h */
-	NULL,					/* 01h */
-	"CHECK CONDITION",			/* 02h */
-	NULL,					/* 03h */
-	"CONDITION MET",			/* 04h */
-	NULL,					/* 05h */
-	NULL,					/* 06h */
-	NULL,					/* 07h */
-	"BUSY",					/* 08h */
-	NULL,					/* 09h */
-	NULL,					/* 0Ah */
-	NULL,					/* 0Bh */
-	NULL,					/* 0Ch */
-	NULL,					/* 0Dh */
-	NULL,					/* 0Eh */
-	NULL,					/* 0Fh */
-	"INTERMEDIATE",				/* 10h */
-	NULL,					/* 11h */
-	NULL,					/* 12h */
-	NULL,					/* 13h */
-	"INTERMEDIATE-CONDITION MET",		/* 14h */
-	NULL,					/* 15h */
-	NULL,					/* 16h */
-	NULL,					/* 17h */
-	"RESERVATION CONFLICT",			/* 18h */
-	NULL,					/* 19h */
-	NULL,					/* 1Ah */
-	NULL,					/* 1Bh */
-	NULL,					/* 1Ch */
-	NULL,					/* 1Dh */
-	NULL,					/* 1Eh */
-	NULL,					/* 1Fh */
-	NULL,					/* 20h */
-	NULL,					/* 21h */
-	"COMMAND TERMINATED",			/* 22h */
-	NULL,					/* 23h */
-	NULL,					/* 24h */
-	NULL,					/* 25h */
-	NULL,					/* 26h */
-	NULL,					/* 27h */
-	"TASK SET FULL",			/* 28h */
-	NULL,					/* 29h */
-	NULL,					/* 2Ah */
-	NULL,					/* 2Bh */
-	NULL,					/* 2Ch */
-	NULL,					/* 2Dh */
-	NULL,					/* 2Eh */
-	NULL,					/* 2Fh */
-	"ACA ACTIVE",				/* 30h */
-	NULL
-};
-
-static const char *ScsiCommonOpString[] = {
-	"TEST UNIT READY",			/* 00h */
-	"REZERO UNIT (REWIND)",			/* 01h */
-	NULL,					/* 02h */
-	"REQUEST_SENSE",			/* 03h */
-	"FORMAT UNIT (MEDIUM)",			/* 04h */
-	"READ BLOCK LIMITS",			/* 05h */
-	NULL,					/* 06h */
-	"REASSIGN BLOCKS",			/* 07h */
-	"READ(6)",				/* 08h */
-	NULL,					/* 09h */
-	"WRITE(6)",				/* 0Ah */
-	"SEEK(6)",				/* 0Bh */
-	NULL,					/* 0Ch */
-	NULL,					/* 0Dh */
-	NULL,					/* 0Eh */
-	"READ REVERSE",				/* 0Fh */
-	"WRITE_FILEMARKS",			/* 10h */
-	"SPACE(6)",				/* 11h */
-	"INQUIRY",				/* 12h */
-	NULL
-};
-
-static const char *SenseKeyString[] = {
-	"NO SENSE",				/* 0h */
-	"RECOVERED ERROR",			/* 1h */
-	"NOT READY",				/* 2h */
-	"MEDIUM ERROR",				/* 3h */
-	"HARDWARE ERROR",			/* 4h */
-	"ILLEGAL REQUEST",			/* 5h */
-	"UNIT ATTENTION",			/* 6h */
-	"DATA PROTECT",				/* 7h */
-	"BLANK CHECK",				/* 8h */
-	"VENDOR-SPECIFIC",			/* 9h */
-	"ABORTED COPY",				/* Ah */
-	"ABORTED COMMAND",			/* Bh */
-	"EQUAL (obsolete)",			/* Ch */
-	"VOLUME OVERFLOW",			/* Dh */
-	"MISCOMPARE",				/* Eh */
-	"RESERVED",				/* Fh */
-	NULL
-};
-
-#define SPECIAL_ASCQ(c,q) \
-	(((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int dump_cdb(char *foo, unsigned char *cdb)
-{
-	int i, grpCode, cdbLen;
-	int l = 0;
-
-	grpCode = cdb[0] >> 5;
-	if (grpCode < 1)
-		cdbLen = 6;
-	else if (grpCode < 3)
-		cdbLen = 10;
-	else if (grpCode == 5)
-		cdbLen = 12;
-	else
-		cdbLen = 16;
-
-	for (i=0; i < cdbLen; i++)
-		l += sprintf(foo+l, " %02X", cdb[i]);
-
-	return l;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*  Do ASC/ASCQ lookup/grindage to English readable string(s)  */
-static const char * ascq_set_strings_4max(
-		u8 ASC, u8 ASCQ,
-		const char **s1, const char **s2, const char **s3, const char **s4)
-{
-	static const char *asc_04_part1_string = "LOGICAL UNIT ";
-	static const char *asc_04_part2a_string = "NOT READY, ";
-	static const char *asc_04_part2b_string = "IS ";
-	static const char *asc_04_ascq_NN_part3_strings[] = {	/* ASC ASCQ (hex) */
-	  "CAUSE NOT REPORTABLE",				/* 04 00 */
-	  "IN PROCESS OF BECOMING READY",			/* 04 01 */
-	  "INITIALIZING CMD. REQUIRED",				/* 04 02 */
-	  "MANUAL INTERVENTION REQUIRED",			/* 04 03 */
-	  /* Add	" IN PROGRESS" to all the following... */
-	  "FORMAT",						/* 04 04 */
-	  "REBUILD",						/* 04 05 */
-	  "RECALCULATION",					/* 04 06 */
-	  "OPERATION",						/* 04 07 */
-	  "LONG WRITE",						/* 04 08 */
-	  "SELF-TEST",						/* 04 09 */
-	  NULL
-	};
-	static char *asc_04_part4_string = " IN PROGRESS";
-
-	static char *asc_29_ascq_NN_strings[] = {		/* ASC ASCQ (hex) */
-	  "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED",	/* 29 00 */
-	  "POWER ON OCCURRED",					/* 29 01 */
-	  "SCSI BUS RESET OCCURRED",				/* 29 02 */
-	  "BUS DEVICE RESET FUNCTION OCCURRED",			/* 29 03 */
-	  "DEVICE INTERNAL RESET",				/* 29 04 */
-	  "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED",		/* 29 05 */
-	  "TRANSCEIVER MODE CHANGED TO LVD",			/* 29 06 */
-	  NULL
-	};
-	static char *ascq_vendor_uniq = "(Vendor Unique)";
-	static char *ascq_noone = "(no matching ASC/ASCQ description found)";
-	int idx;
-
-	*s1 = *s2 = *s3 = *s4 = "";		/* set'em all to the empty "" string */
-
-	/* CHECKME! Need lock/sem?
-	 *  Update and examine for isense module presense.
-	 */
-	mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
-
-	if (mptscsih_ASCQ_TablePtr == NULL) {
-		/* 2nd chances... */
-		if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
-			*s1 = asc_04_part1_string;
-			*s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
-			*s3 = asc_04_ascq_NN_part3_strings[ASCQ];
-			/* check for " IN PROGRESS" ones */
-			if (ASCQ >= 0x04)
-				*s4 = asc_04_part4_string;
-		} else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
-			*s1 = asc_29_ascq_NN_strings[ASCQ];
-		/*
-		 *	Else { leave all *s[1-4] values pointing to the empty "" string }
-		 */
-		return *s1;
-	}
-
-	/*
-	 * Need to check ASC here; if it is "special," then
-	 * the ASCQ is variable, and indicates failed component number.
-	 * We must treat the ASCQ as a "don't care" while searching the
-	 * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
-	 * on when we actually need to identify the failed component.
-	 */
-	if (SPECIAL_ASCQ(ASC,ASCQ))
-		ASCQ = 0xFF;
-
-	/* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
-	for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
-		if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) {
-			*s1 = mptscsih_ASCQ_TablePtr[idx].Description;
-			return *s1;
-		}
-
-	if ((ASC >= 0x80) || (ASCQ >= 0x80))
-		*s1 = ascq_vendor_uniq;
-	else
-		*s1 = ascq_noone;
-
-	return *s1;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  SCSI Information Report; desired output format...
- *---
-SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION)
-  Key=6h (UNIT ATTENTION); FRU=03h
-  ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
-  CDB: 00 00 00 00 00 00 - TestUnitReady
- *---
- */
-/*
- *  SCSI Error Report; desired output format...
- *---
-SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
-  SCSI_Status=02h (CHECK CONDITION)
-  Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
-  SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
-  SenseKey=6h (UNIT ATTENTION); FRU=03h
-  ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
- *---
- */
-
-int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
-{
-	char		 foo[512];
-	char		 buf2[32];
-	char		*statstr;
-	const char	*opstr;
-	int		 sk		= SD_Sense_Key(ioop->sensePtr);
-	const char	*skstr		= SenseKeyString[sk];
-	unsigned char	 asc		= SD_ASC(ioop->sensePtr);
-	unsigned char	 ascq		= SD_ASCQ(ioop->sensePtr);
-	int		 l;
-
-	/* Change the error logging to only report errors on
-	 * read and write commands. Ignore errors on other commands.
-	 * Should this be configurable via proc?
-	 */
-	switch (ioop->cdbPtr[0]) {
-	case READ_6:
-	case WRITE_6:
-	case READ_10:
-	case WRITE_10:
-	case READ_12:
-	case WRITE_12:
-	case READ_16:
-	case WRITE_16:
-		break;
-	default:
-		return 0;
-	}
-
-	/*
-	 *  More quiet mode.
-	 *  Filter out common, repetitive, warning-type errors...  like:
-	 *    POWER ON (06,29/00 or 06,29/01),
-	 *    SPINNING UP (02,04/01),
-	 *    LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
-	 */
-	if (sk == SK_NO_SENSE) {
-		return 0;
-	}
-
-	if (	(sk==SK_UNIT_ATTENTION	&& asc==0x29 && (ascq==0x00 || ascq==0x01))
-	     || (sk==SK_NOT_READY	&& asc==0x04 && (ascq==0x01 || ascq==0x02))
-	     || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
-	   )
-	{
-		/* Do nothing! */
-		return 0;
-	}
-
-	/* Prevent the system from continually writing to the log
-	 * if a medium is not found: 02 3A 00
-	 * Changer issues: TUR, Read Capacity, Table of Contents continually
-	 */
-	if (sk==SK_NOT_READY && asc==0x3A) {
-		if (ioop->cdbPtr == NULL) {
-			return 0;
-		} else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
-			(ioop->cdbPtr[0] == CMD_ReadCapacity) ||
-			(ioop->cdbPtr[0] == 0x43)) {
-			return 0;
-		}
-	}
-	if (sk==SK_UNIT_ATTENTION) {
-		if (ioop->cdbPtr == NULL)
-			return 0;
-		else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
-			return 0;
-	}
-
-	/*
-	 *  Protect ourselves...
-	 */
-	if (ioop->cdbPtr == NULL)
-		ioop->cdbPtr = dummyCDB;
-	if (ioop->sensePtr == NULL)
-		ioop->sensePtr = dummySenseData;
-	if (ioop->inqPtr == NULL)
-		ioop->inqPtr = dummyInqData;
-	if (ioop->dataPtr == NULL)
-		ioop->dataPtr = dummyScsiData;
-
-	statstr = NULL;
-	if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
-	    ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
-		(void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
-		statstr = buf2;
-	}
-
-	opstr = NULL;
-	if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
-		opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
-	else if (mpt_ScsiOpcodesPtr)
-		opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
-
-	l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n",
-			  ioop->DevIDStr,
-			  ioop->SCSIStatus,
-			  statstr);
-	l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
-		  sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
-	{
-		const char	*x1, *x2, *x3, *x4;
-		x1 = x2 = x3 = x4 = "";
-		x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
-		if (x1 != NULL) {
-			if (x1[0] != '(')
-				l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
-			else
-				l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
-		}
-	}
-	l += sprintf(foo+l, "\n CDB:");
-	l += dump_cdb(foo+l, ioop->cdbPtr);
-	if (opstr)
-		l += sprintf(foo+l, " - \"%s\"", opstr);
-	l += sprintf(foo+l, "\n");
-
-	PrintF(("%s\n", foo));
-
-	return l;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mptscsih_initTarget - Target, LUN alloc/free functionality.
@@ -4176,48 +3347,33 @@
 {
 	int		indexed_lun, lun_index;
 	VirtDevice	*vdev;
+	ScsiCfgData	*pSpi;
 	char		data_56;
 
-	dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
+	dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
 			hd->ioc->name, bus_id, target_id, lun, hd));
 
-	/* Is LUN supported? If so, upper 3 bits will be 0
+	/* Is LUN supported? If so, upper 2 bits will be 0
 	* in first byte of inquiry data.
 	*/
 	if (data[0] & 0xe0)
 		return;
 
-	vdev = hd->Targets[target_id];
+	if ((vdev = hd->Targets[target_id]) == NULL) {
+		return;
+	}
 
 	lun_index = (lun >> 5);  /* 32 luns per lun_index */
 	indexed_lun = (lun % 32);
 	vdev->luns[lun_index] |= (1 << indexed_lun);
 
-	vdev->raidVolume = 0;
 	if (hd->is_spi) {
-		if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
-			vdev->raidVolume = 1;
-			ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
-		}
-	}
-
-	if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-		if ( dlen > 8 ) {
-			memcpy (vdev->inq_data, data, 8);
-		} else {
-			memcpy (vdev->inq_data, data, dlen);
-		}
-		vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-
-		/* If LUN 0, tape and have not done DV, set the DV flag.
-		 */
-		if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
-			ScsiCfgData *pSpi = &hd->ioc->spi_data;
-			if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
-				pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
-		}
-
-		if ( (data[0] == SCSI_TYPE_PROC) &&
+		if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+			/* Treat all Processors as SAF-TE if
+			 * command line option is set */
+			vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+			mptscsih_writeIOCPage4(hd, target_id, bus_id);
+		}else if ((data[0] == TYPE_PROCESSOR) &&
 			!(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
 			if ( dlen > 49 ) {
 				vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
@@ -4230,30 +3386,51 @@
 					vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
 					mptscsih_writeIOCPage4(hd, target_id, bus_id);
 				}
-			} else {
-				/* Treat all Processors as SAF-TE if
-				 * command line option is set */
-				if ( hd->ioc->spi_data.Saf_Te ) {
-					vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-					mptscsih_writeIOCPage4(hd, target_id, bus_id);
-				}
 			}
 		}
+		if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+			if ( dlen > 8 ) {
+				memcpy (vdev->inq_data, data, 8);
+			} else {
+				memcpy (vdev->inq_data, data, dlen);
+			}
 
-		data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
-		if (dlen > 56) {
-			if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
-			/* Update the target capabilities
+			/* If have not done DV, set the DV flag.
 			 */
-				data_56 = data[56];
-				vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
+			pSpi = &hd->ioc->spi_data;
+			if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
+				if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
+					pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
+			}
+
+			vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+
+
+			data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
+			if (dlen > 56) {
+				if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+				/* Update the target capabilities
+				 */
+					data_56 = data[56];
+					vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
+				}
+			}
+			mptscsih_setTargetNegoParms(hd, vdev, data_56);
+		} else {
+			/* Initial Inquiry may not request enough data bytes to
+			 * obtain byte 57.  DV will; if target doesn't return
+			 * at least 57 bytes, data[56] will be zero. */
+			if (dlen > 56) {
+				if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+				/* Update the target capabilities
+				 */
+					data_56 = data[56];
+					vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
+					mptscsih_setTargetNegoParms(hd, vdev, data_56);
+				}
 			}
 		}
-		mptscsih_setTargetNegoParms(hd, vdev, data_56);
 	}
-
-	dprintk((KERN_INFO "  target = %p\n", vdev));
-	return;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -4262,12 +3439,12 @@
  *  the Inquiry data, adapter capabilities, and NVRAM settings.
  *
  */
-void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
+static void
+mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
 {
 	ScsiCfgData *pspi_data = &hd->ioc->spi_data;
 	int  id = (int) target->target_id;
 	int  nvram;
-	char canQ = 0;
 	VirtDevice	*vdev;
 	int ii;
 	u8 width = MPT_NARROW;
@@ -4276,14 +3453,6 @@
 	u8 version, nfactor;
 	u8 noQas = 1;
 
-	if (!hd->is_spi) {
-		if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-			if (target->inq_data[7] & 0x02)
-				target->tflags |= MPT_TARGET_FLAGS_Q_YES;
-		}
-		return;
-	}
-
 	target->negoFlags = pspi_data->noQas;
 
 	/* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
@@ -4293,137 +3462,152 @@
 
 	/* Set flags based on Inquiry data
 	 */
-	if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-		version = target->inq_data[2] & 0x07;
-		if (version < 2) {
-			width = 0;
-			factor = MPT_ULTRA2;
-			offset = pspi_data->maxSyncOffset;
-		} else {
-			if (target->inq_data[7] & 0x20) {
-				width = 1;
-			}
+	version = target->inq_data[2] & 0x07;
+	if (version < 2) {
+		width = 0;
+		factor = MPT_ULTRA2;
+		offset = pspi_data->maxSyncOffset;
+		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+	} else {
+		if (target->inq_data[7] & 0x20) {
+			width = 1;
+		}
 
-			if (target->inq_data[7] & 0x10) {
-				/* bits 2 & 3 show Clocking support
-				 */
+		if (target->inq_data[7] & 0x10) {
+			factor = pspi_data->minSyncFactor;
+			if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
+				/* bits 2 & 3 show Clocking support */
 				if ((byte56 & 0x0C) == 0)
 					factor = MPT_ULTRA2;
 				else {
 					if ((byte56 & 0x03) == 0)
 						factor = MPT_ULTRA160;
-					else
+					else {
 						factor = MPT_ULTRA320;
-				}
-				offset = pspi_data->maxSyncOffset;
-
-				/* If RAID, never disable QAS
-				 * else if non RAID, do not disable
-				 *   QAS if bit 1 is set
-				 * bit 1 QAS support, non-raid only
-				 * bit 0 IU support
-				 */
-				if ((target->raidVolume == 1) || (byte56 & 0x02)) {
-					noQas = 0;
+						if (byte56 & 0x02)
+						{
+							ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
+							noQas = 0;
+						}
+						if (target->inq_data[0] == TYPE_TAPE) {
+							if (byte56 & 0x01)
+								target->negoFlags |= MPT_TAPE_NEGO_IDP;
+						}
+					}
 				}
 			} else {
-				factor = MPT_ASYNC;
-				offset = 0;
+				ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
+				noQas = 0;
 			}
-		}
+				
+			offset = pspi_data->maxSyncOffset;
 
-		if (target->inq_data[7] & 0x02) {
-			canQ = 1;
+			/* If RAID, never disable QAS
+			 * else if non RAID, do not disable
+			 *   QAS if bit 1 is set
+			 * bit 1 QAS support, non-raid only
+			 * bit 0 IU support
+			 */
+			if (target->raidVolume == 1) {
+				noQas = 0;
+			}
+		} else {
+			factor = MPT_ASYNC;
+			offset = 0;
 		}
+	}
 
-		/* Update tflags based on NVRAM settings. (SCSI only)
-		 */
-		if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-			nvram = pspi_data->nvram[id];
-			nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+	if ( (target->inq_data[7] & 0x02) == 0) {
+		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+	}
 
-			if (width)
-				width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+	/* Update tflags based on NVRAM settings. (SCSI only)
+	 */
+	if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+		nvram = pspi_data->nvram[id];
+		nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
 
-			if (offset > 0) {
-				/* Ensure factor is set to the
-				 * maximum of: adapter, nvram, inquiry
-				 */
-				if (nfactor) {
-					if (nfactor < pspi_data->minSyncFactor )
-						nfactor = pspi_data->minSyncFactor;
+		if (width)
+			width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
 
-					factor = max(factor, nfactor);
-					if (factor == MPT_ASYNC)
-						offset = 0;
-				} else {
+		if (offset > 0) {
+			/* Ensure factor is set to the
+			 * maximum of: adapter, nvram, inquiry
+			 */
+			if (nfactor) {
+				if (nfactor < pspi_data->minSyncFactor )
+					nfactor = pspi_data->minSyncFactor;
+
+				factor = max(factor, nfactor);
+				if (factor == MPT_ASYNC)
 					offset = 0;
-					factor = MPT_ASYNC;
-				}
 			} else {
+				offset = 0;
 				factor = MPT_ASYNC;
-			}
 		}
-
-		/* Make sure data is consistent
-		 */
-		if ((!width) && (factor < MPT_ULTRA2)) {
-			factor = MPT_ULTRA2;
+		} else {
+			factor = MPT_ASYNC;
 		}
+	}
 
-		/* Save the data to the target structure.
-		 */
-		target->minSyncFactor = factor;
-		target->maxOffset = offset;
-		target->maxWidth = width;
-		if (canQ) {
-			target->tflags |= MPT_TARGET_FLAGS_Q_YES;
-		}
+	/* Make sure data is consistent
+	 */
+	if ((!width) && (factor < MPT_ULTRA2)) {
+		factor = MPT_ULTRA2;
+	}
 
-		target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
+	/* Save the data to the target structure.
+	 */
+	target->minSyncFactor = factor;
+	target->maxOffset = offset;
+	target->maxWidth = width;
 
-		/* Disable unused features.
-		 */
-		if (!width)
-			target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
 
-		if (!offset)
-			target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+	/* Disable unused features.
+	 */
+	if (!width)
+		target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
 
-		/* GEM, processor WORKAROUND
-		 */
-		if (((target->inq_data[0] & 0x1F) == 0x03)
-			|| ((target->inq_data[0] & 0x1F) > 0x08)) {
-			target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
-			pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
-		} else {
-			if (noQas && (pspi_data->noQas == 0)) {
-				pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
-				target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-
-				/* Disable QAS in a mixed configuration case
-		 		*/
-
-				ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
-				for (ii = 0; ii < id; ii++) {
-					if ( (vdev = hd->Targets[ii]) ) {
-						vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-					}
-				}
+	if (!offset)
+		target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+
+	if ( factor > MPT_ULTRA320 )
+		noQas = 0;
+
+	/* GEM, processor WORKAROUND
+	 */
+	if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
+		target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
+		pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
+	} else {
+		if (noQas && (pspi_data->noQas == 0)) {
+			pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+			target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+
+			/* Disable QAS in a mixed configuration case
+	 		*/
+
+			ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+			for (ii = 0; ii < id; ii++) {
+				if ( (vdev = hd->Targets[ii]) ) {
+					vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+					mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
+				}	
 			}
 		}
-		
-		/* Write SDP1 on this I/O to this target */
-		if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
-			mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
-			pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
-		} else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
-			mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
-			pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
-		}
 	}
 
-	return;
+	/* Write SDP1 on this I/O to this target */
+	if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
+		ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
+		mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
+		pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
+	} else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
+		ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
+		mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
+		pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
+	}
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -4437,14 +3621,18 @@
 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
 {
 	u8 cmd;
+	ScsiCfgData *pSpi;
 
+	ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", 
+		pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
+	
 	if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
 		return;
 
 	cmd = pReq->CDB[0];
 
 	if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
-		ScsiCfgData *pSpi = &hd->ioc->spi_data;
+		pSpi = &hd->ioc->spi_data;
 		if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
 			/* Set NEED_DV for all hidden disks
 			 */
@@ -4510,6 +3698,8 @@
 			*requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
 			if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
 				*requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
+			if (flags & MPT_TAPE_NEGO_IDP)
+				*requestedPtr |= 0x08000000;
 		} else if (factor < MPT_ULTRA2) {
 			*requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
 		}
@@ -4624,6 +3814,16 @@
 			//negoFlags = MPT_TARGET_NO_NEGO_SYNC;
 		}
 
+		/* If id is not a raid volume, get the updated
+		 * transmission settings from the target structure.
+		 */
+		if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
+			width = pTarget->maxWidth;
+			factor = pTarget->minSyncFactor;
+			offset = pTarget->maxOffset;
+			negoFlags = pTarget->negoFlags;
+		}
+		
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 		/* Force to async and narrow if DV has not been executed
 		 * for this ID
@@ -4635,21 +3835,13 @@
 		}
 #endif
 
-		/* If id is not a raid volume, get the updated
-		 * transmission settings from the target structure.
-		 */
-		if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
-			width = pTarget->maxWidth;
-			factor = pTarget->minSyncFactor;
-			offset = pTarget->maxOffset;
-			negoFlags = pTarget->negoFlags;
-		}
-
 		if (flags & MPT_SCSICFG_BLK_NEGO)
 			negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
 
 		mptscsih_setDevicePage1Flags(width, factor, offset,
 					&requested, &configuration, negoFlags);
+		dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
+			target_id, width, factor, offset, negoFlags, requested, configuration));
 
 		/* Get a MF for this command.
 		 */
@@ -4754,9 +3946,6 @@
 		return -EAGAIN;
 	}
 
-	ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
-		ioc->name, mf, target_id));
-
 	/* Set the request and the data pointers.
 	 * Place data at end of MF.
 	 */
@@ -4793,9 +3982,9 @@
 
 	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
 
-	dsprintk((MYIOC_s_INFO_FMT
-		"writeIOCPage4: pgaddr 0x%x\n",
-			ioc->name, (target_id | (bus<<8))));
+	dinitprintk((MYIOC_s_INFO_FMT
+		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
+			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
 
 	mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
 
@@ -4922,13 +4111,15 @@
 	} else {
 		SCSIIOReply_t	*pReply;
 		u16		 status;
+		u8		 scsi_status;
 
 		pReply = (SCSIIOReply_t *) mr;
 
 		status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+		scsi_status = pReply->SCSIStatus;
 
 		ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
-			     status, pReply->SCSIState, pReply->SCSIStatus,
+			     status, pReply->SCSIState, scsi_status,
 			     le32_to_cpu(pReply->IOCLogInfo)));
 
 		switch(status) {
@@ -4973,7 +4164,7 @@
 				/* save sense data in global structure
 				 */
 				completionCode = MPT_SCANDV_SENSE;
-				hd->pLocal->scsiStatus = pReply->SCSIStatus;
+				hd->pLocal->scsiStatus = scsi_status;
 				sense_data = ((u8 *)hd->ioc->sense_buf_pool +
 					(req_idx * MPT_SENSE_BUFFER_ALLOC));
 
@@ -4984,7 +4175,7 @@
 				ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
 						sense_data));
 			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
-				if (pReq->CDB[0] == CMD_Inquiry)
+				if (pReq->CDB[0] == INQUIRY)
 					completionCode = MPT_SCANDV_ISSUE_SENSE;
 				else
 					completionCode = MPT_SCANDV_DID_RESET;
@@ -4994,11 +4185,8 @@
 			else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
 				completionCode = MPT_SCANDV_DID_RESET;
 			else {
-				/* If no error, this will be equivalent
-				 * to MPT_SCANDV_GOOD
-				 */
 				completionCode = MPT_SCANDV_GOOD;
-				hd->pLocal->scsiStatus = pReply->SCSIStatus;
+				hd->pLocal->scsiStatus = scsi_status;
 			}
 			break;
 
@@ -5025,7 +4213,7 @@
 	 */
 wakeup:
 	/* Free Chain buffers (will never chain) in scan or dv */
-	//mptscsih_freeChainBuffers(hd, req_idx);
+	//mptscsih_freeChainBuffers(ioc, req_idx);
 
 	/*
 	 * Wake up the original calling thread
@@ -5197,7 +4385,7 @@
 	/* Set command specific information
 	 */
 	switch (cmd) {
-	case CMD_Inquiry:
+	case INQUIRY:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5205,13 +4393,13 @@
 		cmdTimeout = 10;
 		break;
 
-	case CMD_TestUnitReady:
+	case TEST_UNIT_READY:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		cmdTimeout = 10;
 		break;
 
-	case CMD_StartStopUnit:
+	case START_STOP:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5219,7 +4407,7 @@
 		cmdTimeout = 15;
 		break;
 
-	case CMD_RequestSense:
+	case REQUEST_SENSE:
 		cmdLen = 6;
 		CDB[0] = cmd;
 		CDB[4] = io->size;
@@ -5227,7 +4415,7 @@
 		cmdTimeout = 10;
 		break;
 
-	case CMD_ReadBuffer:
+	case READ_BUFFER:
 		cmdLen = 10;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5246,7 +4434,7 @@
 		cmdTimeout = 10;
 		break;
 
-	case CMD_WriteBuffer:
+	case WRITE_BUFFER:
 		cmdLen = 10;
 		dir = MPI_SCSIIO_CONTROL_WRITE;
 		CDB[0] = cmd;
@@ -5261,21 +4449,21 @@
 		cmdTimeout = 10;
 		break;
 
-	case CMD_Reserve6:
+	case RESERVE:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
 		cmdTimeout = 10;
 		break;
 
-	case CMD_Release6:
+	case RELEASE:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
 		cmdTimeout = 10;
 		break;
 
-	case CMD_SynchronizeCache:
+	case SYNCHRONIZE_CACHE:
 		cmdLen = 10;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5331,7 +4519,7 @@
 	else
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
 
-	if (cmd == CMD_RequestSense) {
+	if (cmd == REQUEST_SENSE) {
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
 		ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
 			hd->ioc->name, cmd));
@@ -5439,7 +4627,7 @@
 	/* Following parameters will not change
 	 * in this routine.
 	 */
-	iocmd.cmd = CMD_SynchronizeCache;
+	iocmd.cmd = SYNCHRONIZE_CACHE;
 	iocmd.flags = 0;
 	iocmd.physDiskNum = -1;
 	iocmd.data = NULL;
@@ -5509,6 +4697,9 @@
 			/* Force to async, narrow */
 			mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
 					&configuration, flags);
+			dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+				"offset=0 negoFlags=%x request=%x config=%x\n",
+				id, flags, requested, configuration));
 			pcfg1Data->RequestedParameters = le32_to_cpu(requested);
 			pcfg1Data->Reserved = 0;
 			pcfg1Data->Configuration = le32_to_cpu(configuration);
@@ -5681,11 +4872,6 @@
 						}
 					}
 
-					/* Post OS IOs that were pended while
-					 * DV running.
-					 */
-					post_pendingQ_commands(hd);
-
 					if (hd->ioc->spi_data.noQas)
 						mptscsih_qas_check(hd, id);
 				}
@@ -5741,11 +4927,14 @@
 		if ((pTarget != NULL) && (!pTarget->raidVolume)) {
 			if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
 				pTarget->negoFlags |= hd->ioc->spi_data.noQas;
+				dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
 				mptscsih_writeSDP1(hd, 0, ii, 0);
 			}
 		} else {
-			if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
+			if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
+				dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
 				mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
+			}
 		}
 	}
 	return;
@@ -5824,7 +5013,7 @@
 	lun = 0;
 	bus = (u8) bus_number;
 	ddvtprintk((MYIOC_s_NOTE_FMT
-			"DV started: bus=%d, id %d dv @ %p\n",
+			"DV started: bus=%d, id=%d dv @ %p\n",
 			ioc->name, bus, id, &dv));
 
 	/* Prep DV structure
@@ -5838,8 +5027,6 @@
 	 */
 	dv.cmd = MPT_GET_NVRAM_VALS;
 	mptscsih_dv_parms(hd, &dv, NULL);
-	if ((!dv.max.width) && (!dv.max.offset))
-		return 0;
 
 	/* Prep SCSI IO structure
 	 */
@@ -5851,15 +5038,6 @@
 	iocmd.rsvd = iocmd.rsvd2 = 0;
 
 	pTarget = hd->Targets[id];
-	if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-		/* Another GEM workaround. Check peripheral device type,
-		 * if PROCESSOR, quit DV.
-		 */
-		if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
-			pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
-			return 0;
-		}
-	}
 
 	/* Use tagged commands if possible.
 	 */
@@ -5959,7 +5137,7 @@
 
 	/* Finish iocmd inititialization - hidden or visible disk? */
 	if (ioc->spi_data.pIocPg3) {
-		/* Searc IOC page 3 for matching id
+		/* Search IOC page 3 for matching id
 		 */
 		Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
 		int		numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
@@ -6001,7 +5179,7 @@
 	 */
 	hd->pLocal = NULL;
 	readPage0 = 0;
-	sz = SCSI_STD_INQUIRY_BYTES;
+	sz = SCSI_MAX_INQUIRY_BYTES;
 	rc = MPT_SCANDV_GOOD;
 	while (1) {
 		ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
@@ -6026,7 +5204,7 @@
 				((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
 				(hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
 
-				iocmd.cmd = CMD_RequestSense;
+				iocmd.cmd = REQUEST_SENSE;
 				iocmd.data_dma = buf1_dma;
 				iocmd.data = pbuf1;
 				iocmd.size = 0x12;
@@ -6046,10 +5224,11 @@
 				goto target_done;
 		}
 
-		iocmd.cmd = CMD_Inquiry;
+		iocmd.cmd = INQUIRY;
 		iocmd.data_dma = buf1_dma;
 		iocmd.data = pbuf1;
 		iocmd.size = sz;
+		memset(pbuf1, 0x00, sz);
 		if (mptscsih_do_cmd(hd, &iocmd) < 0)
 			goto target_done;
 		else {
@@ -6057,7 +5236,7 @@
 				goto target_done;
 			rc = hd->pLocal->completion;
 			if (rc == MPT_SCANDV_GOOD) {
-				if (hd->pLocal->scsiStatus == STS_BUSY) {
+				if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
 					if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
 						retcode = 1;
 					else
@@ -6087,7 +5266,17 @@
 		/* Another GEM workaround. Check peripheral device type,
 		 * if PROCESSOR, quit DV.
 		 */
-		if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08))
+		if (inq0 == TYPE_PROCESSOR) {
+			mptscsih_initTarget(hd,
+				bus,
+				id,
+				lun,
+				pbuf1,
+				sz);
+			goto target_done;
+		}
+
+		if (inq0 > 0x08)
 			goto target_done;
 
 		if (mptscsih_do_cmd(hd, &iocmd) < 0)
@@ -6111,6 +5300,9 @@
 				if ((pbuf1[56] & 0x02) == 0) {
 					pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
 					hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+					ddvprintk((MYIOC_s_NOTE_FMT 
+					    "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", 
+					    ioc->name, id, pbuf1[56]));
 				}
 			}
 		}
@@ -6127,10 +5319,11 @@
 		if ((!dv.now.width) && (!dv.now.offset))
 			goto target_done;
 
-		iocmd.cmd = CMD_Inquiry;
+		iocmd.cmd = INQUIRY;
 		iocmd.data_dma = buf2_dma;
 		iocmd.data = pbuf2;
 		iocmd.size = sz;
+		memset(pbuf2, 0x00, sz);
 		if (mptscsih_do_cmd(hd, &iocmd) < 0)
 			goto target_done;
 		else if (hd->pLocal == NULL)
@@ -6183,14 +5376,26 @@
 					if (memcmp(pbuf1, pbuf2, sz) != 0) {
 						if (!firstPass)
 							doFallback = 1;
-					} else
+					} else {
+						ddvprintk((MYIOC_s_NOTE_FMT 
+						    "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
+						hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
+						mptscsih_initTarget(hd,
+							bus,
+							id,
+							lun,
+							pbuf1,
+							sz);
 						break;	/* test complete */
+					}
 				}
 
 
 			} else if (rc == MPT_SCANDV_ISSUE_SENSE)
 				doFallback = 1;	/* set fallback flag */
-			else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
+			else if ((rc == MPT_SCANDV_DID_RESET) || 
+				 (rc == MPT_SCANDV_SENSE) || 
+				 (rc == MPT_SCANDV_FALLBACK))
 				doFallback = 1;	/* set fallback flag */
 			else
 				goto target_done;
@@ -6199,6 +5404,10 @@
 		}
 	}
 	ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
+
+	if (driver_setup.dv == 0)
+		goto target_done;
+
 	inq0 = (*pbuf1) & 0x1F;
 
 	/* Continue only for disks
@@ -6222,7 +5431,7 @@
 	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 	cfg.dir = 1;
 
-	iocmd.cmd = CMD_TestUnitReady;
+	iocmd.cmd = TEST_UNIT_READY;
 	iocmd.data_dma = -1;
 	iocmd.data = NULL;
 	iocmd.size = 0;
@@ -6245,14 +5454,14 @@
 				"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
 				ioc->name, skey, asc, ascq));
 
-			if (skey == SK_UNIT_ATTENTION)
+			if (skey == UNIT_ATTENTION)
 				notDone++; /* repeat */
-			else if ((skey == SK_NOT_READY) &&
+			else if ((skey == NOT_READY) &&
 					(asc == 0x04)&&(ascq == 0x01)) {
 				/* wait then repeat */
 				mdelay (2000);
 				notDone++;
-			} else if ((skey == SK_NOT_READY) && (asc == 0x3A)) {
+			} else if ((skey == NOT_READY) && (asc == 0x3A)) {
 				/* no medium, try read test anyway */
 				notDone = 0;
 			} else {
@@ -6266,7 +5475,7 @@
 			goto target_done;
 	}
 
-	iocmd.cmd = CMD_ReadBuffer;
+	iocmd.cmd = READ_BUFFER;
 	iocmd.data_dma = buf1_dma;
 	iocmd.data = pbuf1;
 	iocmd.size = 4;
@@ -6314,11 +5523,11 @@
 					ddvprintk((MYIOC_s_INFO_FMT
 						"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
 						ioc->name, skey, asc, ascq));
-					if (skey == SK_ILLEGAL_REQUEST) {
+					if (skey == ILLEGAL_REQUEST) {
 						notDone = 0;
-					} else if (skey == SK_UNIT_ATTENTION) {
+					} else if (skey == UNIT_ATTENTION) {
 						notDone++; /* repeat */
-					} else if ((skey == SK_NOT_READY) &&
+					} else if ((skey == NOT_READY) &&
 						(asc == 0x04)&&(ascq == 0x01)) {
 						/* wait then repeat */
 						mdelay (2000);
@@ -6373,14 +5582,14 @@
 	for (patt = 0; patt < 4; patt++) {
 		ddvprintk(("Pattern %d\n", patt));
 		if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
-			iocmd.cmd = CMD_TestUnitReady;
+			iocmd.cmd = TEST_UNIT_READY;
 			iocmd.data_dma = -1;
 			iocmd.data = NULL;
 			iocmd.size = 0;
 			if (mptscsih_do_cmd(hd, &iocmd) < 0)
 				goto target_done;
 
-			iocmd.cmd = CMD_Release6;
+			iocmd.cmd = RELEASE;
 			iocmd.data_dma = -1;
 			iocmd.data = NULL;
 			iocmd.size = 0;
@@ -6402,7 +5611,7 @@
 
 		repeat = 5;
 		while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
-			iocmd.cmd = CMD_Reserve6;
+			iocmd.cmd = RESERVE;
 			iocmd.data_dma = -1;
 			iocmd.data = NULL;
 			iocmd.size = 0;
@@ -6425,7 +5634,7 @@
 					ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
 							skey, asc, ascq));
 
-					if ((skey == SK_NOT_READY) && (asc == 0x04)&&
+					if ((skey == NOT_READY) && (asc == 0x04)&&
 									(ascq == 0x01)) {
 						/* wait then repeat */
 						mdelay (2000);
@@ -6444,7 +5653,7 @@
 		}
 
 		mptscsih_fillbuf(pbuf1, sz, patt, 1);
-		iocmd.cmd = CMD_WriteBuffer;
+		iocmd.cmd = WRITE_BUFFER;
 		iocmd.data_dma = buf1_dma;
 		iocmd.data = pbuf1;
 		iocmd.size = sz;
@@ -6485,10 +5694,10 @@
 				ddvprintk((MYIOC_s_INFO_FMT
 					"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
 					hd->pLocal->sense[12], hd->pLocal->sense[13]));
-				if (skey == SK_UNIT_ATTENTION) {
+				if (skey == UNIT_ATTENTION) {
 					patt = -1;
 					continue;
-				} else if (skey == SK_ILLEGAL_REQUEST) {
+				} else if (skey == ILLEGAL_REQUEST) {
 					if (iocmd.flags & MPT_ICFLAG_ECHO) {
 						if (dataBufSize >= bufsize) {
 							iocmd.flags &= ~MPT_ICFLAG_ECHO;
@@ -6506,7 +5715,7 @@
 			}
 		}
 
-		iocmd.cmd = CMD_ReadBuffer;
+		iocmd.cmd = READ_BUFFER;
 		iocmd.data_dma = buf2_dma;
 		iocmd.data = pbuf2;
 		iocmd.size = sz;
@@ -6581,7 +5790,7 @@
 				ddvprintk((MYIOC_s_INFO_FMT
 					"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
 					hd->pLocal->sense[12], hd->pLocal->sense[13]));
-				if (skey == SK_UNIT_ATTENTION) {
+				if (skey == UNIT_ATTENTION) {
 					patt = -1;
 					continue;
 				}
@@ -6597,7 +5806,7 @@
 
 target_done:
 	if (iocmd.flags & MPT_ICFLAG_RESERVED) {
-		iocmd.cmd = CMD_Release6;
+		iocmd.cmd = RELEASE;
 		iocmd.data_dma = -1;
 		iocmd.data = NULL;
 		iocmd.size = 0;
@@ -6619,8 +5828,11 @@
 	if ((cfg.hdr != NULL) && (retcode == 0)){
 		/* If disk, not U320, disable QAS
 		 */
-		if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
+		if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
 			hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+			ddvprintk((MYIOC_s_NOTE_FMT 
+			    "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
+		}
 
 		dv.cmd = MPT_SAVE;
 		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
@@ -6649,8 +5861,8 @@
 	if (pDvBuf)
 		pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
 
-	ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
-			ioc->name));
+	ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
+			ioc->name, id));
 
 	return retcode;
 }
@@ -6730,8 +5942,8 @@
 		dv->max.offset = offset;
 		dv->max.factor = factor;
 		dv->max.flags = negoFlags;
-		ddvprintk((" width %d, factor %x, offset %x flags %x\n",
-				width, factor, offset, negoFlags));
+		ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
+				id, width, factor, offset, negoFlags));
 		break;
 
 	case MPT_UPDATE_MAX:
@@ -6749,8 +5961,8 @@
 		dv->now.width = dv->max.width;
 		dv->now.offset = dv->max.offset;
 		dv->now.factor = dv->max.factor;
-		ddvprintk(("width %d, factor %x, offset %x, flags %x\n",
-				dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
+		ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
+				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
 		break;
 
 	case MPT_SET_MAX:
@@ -6766,14 +5978,15 @@
 		if (pPage1) {
 			mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
 				dv->now.offset, &val, &configuration, dv->now.flags);
+			dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
+				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
 			pPage1->RequestedParameters = le32_to_cpu(val);
 			pPage1->Reserved = 0;
 			pPage1->Configuration = le32_to_cpu(configuration);
-
 		}
 
-		ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n",
-				dv->now.width, dv->now.factor, dv->now.offset, val, configuration));
+		ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
+				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
 		break;
 
 	case MPT_SET_MIN:
@@ -6790,12 +6003,14 @@
 		if (pPage1) {
 			mptscsih_setDevicePage1Flags (width, factor,
 				offset, &val, &configuration, negoFlags);
+			dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
+				id, width, factor, offset, negoFlags, val, configuration));
 			pPage1->RequestedParameters = le32_to_cpu(val);
 			pPage1->Reserved = 0;
 			pPage1->Configuration = le32_to_cpu(configuration);
 		}
-		ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
-				width, factor, offset, val, configuration));
+		ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
+				id, width, factor, offset, val, configuration, negoFlags));
 		break;
 
 	case MPT_FALLBACK:
@@ -6855,6 +6070,7 @@
 			factor = MPT_ASYNC;
 		}
 		dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
+		dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
 
 		dv->now.width = width;
 		dv->now.offset = offset;
@@ -6865,21 +6081,23 @@
 		if (pPage1) {
 			mptscsih_setDevicePage1Flags (width, factor, offset, &val,
 						&configuration, dv->now.flags);
+			dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
+			     id, width, offset, factor, dv->now.flags, val, configuration));
 
 			pPage1->RequestedParameters = le32_to_cpu(val);
 			pPage1->Reserved = 0;
 			pPage1->Configuration = le32_to_cpu(configuration);
 		}
 
-		ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n",
-			     dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
+		ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
+			     id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
 		break;
 
 	case MPT_SAVE:
 		ddvprintk((MYIOC_s_NOTE_FMT
 			"Saving to Target structure: ", hd->ioc->name));
-		ddvprintk(("offset %d, factor %x, width %d \n",
-			     dv->now.offset, dv->now.factor, dv->now.width));
+		ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
+			     id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
 
 		/* Save these values to target structures
 		 * or overwrite nvram (phys disks only).
diff -Nru a/drivers/message/fusion/scsi3.h b/drivers/message/fusion/scsi3.h
--- a/drivers/message/fusion/scsi3.h	2004-03-10 08:36:33 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,707 +0,0 @@
-/*
- *  linux/drivers/message/fusion/scsi3.h
- *      SCSI-3 definitions and macros.
- *      (Ultimately) SCSI-3 definitions; for now, inheriting
- *      SCSI-2 definitions.
- *
- *  Copyright (c) 1996-2004 Steven J. Ralston
- *  Written By: Steven J. Ralston (19960517)
- *  (mailto:sjralston1@netscape.net)
- *  (mailto:mpt_linux_developer@lsil.com)
- *
- *  $Id: scsi3.h,v 1.9 2002/02/27 18:45:02 sralston Exp $
- */
-
-#ifndef SCSI3_H_INCLUDED
-#define SCSI3_H_INCLUDED
-/***************************************************************************/
-
-/****************************************************************************
- *
- *  Includes
- */
-#ifdef __KERNEL__
-#include <linux/types.h>
-#else
-    #ifndef U_STUFF_DEFINED
-    #define U_STUFF_DEFINED
-    typedef unsigned char u8;
-    typedef unsigned short u16;
-    typedef unsigned int u32;
-    #endif
-#endif
-
-/****************************************************************************
- *
- *  Defines
- */
-
-/*
- *    SCSI Commands
- */
-#define CMD_TestUnitReady      0x00
-#define CMD_RezeroUnit         0x01  /* direct-access devices */
-#define CMD_Rewind             0x01  /* sequential-access devices */
-#define CMD_RequestSense       0x03
-#define CMD_FormatUnit         0x04
-#define CMD_ReassignBlock      0x07
-#define CMD_Read6              0x08
-#define CMD_Write6             0x0A
-#define CMD_WriteFilemark      0x10
-#define CMD_Space              0x11
-#define CMD_Inquiry            0x12
-#define CMD_ModeSelect6        0x15
-#define CMD_ModeSense6         0x1A
-#define CMD_Reserve6           0x16
-#define CMD_Release6           0x17
-#define CMD_Erase              0x19
-#define CMD_StartStopUnit      0x1b  /* direct-access devices */
-#define CMD_LoadUnload         0x1b  /* sequential-access devices */
-#define CMD_ReceiveDiagnostic  0x1C
-#define CMD_SendDiagnostic     0x1D
-#define CMD_ReadCapacity       0x25
-#define CMD_Read10             0x28
-#define CMD_Write10            0x2A
-#define CMD_WriteVerify        0x2E
-#define CMD_Verify             0x2F
-#define CMD_SynchronizeCache   0x35
-#define CMD_ReadDefectData     0x37
-#define CMD_WriteBuffer        0x3B
-#define CMD_ReadBuffer         0x3C
-#define CMD_ReadLong           0x3E
-#define CMD_LogSelect          0x4C
-#define CMD_LogSense           0x4D
-#define CMD_ModeSelect10       0x55
-#define CMD_Reserve10          0x56
-#define CMD_Release10          0x57
-#define CMD_ModeSense10        0x5A
-#define CMD_PersistReserveIn   0x5E
-#define CMD_PersistReserveOut  0x5F
-#define CMD_ReportLuns         0xA0
-
-/*
- *    Control byte field
- */
-#define CONTROL_BYTE_NACA_BIT  0x04
-#define CONTROL_BYTE_Flag_BIT  0x02
-#define CONTROL_BYTE_Link_BIT  0x01
-
-/*
- *    SCSI Messages
- */
-#define MSG_COMPLETE             0x00
-#define MSG_EXTENDED             0x01
-#define MSG_SAVE_POINTERS        0x02
-#define MSG_RESTORE_POINTERS     0x03
-#define MSG_DISCONNECT           0x04
-#define MSG_IDERROR              0x05
-#define MSG_ABORT                0x06
-#define MSG_REJECT               0x07
-#define MSG_NOP                  0x08
-#define MSG_PARITY_ERROR         0x09
-#define MSG_LINKED_CMD_COMPLETE  0x0a
-#define MSG_LCMD_COMPLETE_W_FLG  0x0b
-#define MSG_BUS_DEVICE_RESET     0x0c
-#define MSG_ABORT_TAG            0x0d
-#define MSG_CLEAR_QUEUE          0x0e
-#define MSG_INITIATE_RECOVERY    0x0f
-
-#define MSG_RELEASE_RECOVRY      0x10
-#define MSG_TERMINATE_IO         0x11
-
-#define MSG_SIMPLE_QUEUE         0x20
-#define MSG_HEAD_OF_QUEUE        0x21
-#define MSG_ORDERED_QUEUE        0x22
-#define MSG_IGNORE_WIDE_RESIDUE  0x23
-
-#define MSG_IDENTIFY             0x80
-#define MSG_IDENTIFY_W_DISC      0xc0
-
-/*
- *    SCSI Phases
- */
-#define PHS_DATA_OUT  0x00
-#define PHS_DATA_IN   0x01
-#define PHS_COMMAND   0x02
-#define PHS_STATUS    0x03
-#define PHS_MSG_OUT   0x06
-#define PHS_MSG_IN    0x07
-
-/*
- *    Statuses
- */
-#define STS_GOOD                        0x00
-#define STS_CHECK_CONDITION             0x02
-#define STS_CONDITION_MET               0x04
-#define STS_BUSY                        0x08
-#define STS_INTERMEDIATE                0x10
-#define STS_INTERMEDIATE_CONDITION_MET  0x14
-#define STS_RESERVATION_CONFLICT        0x18
-#define STS_COMMAND_TERMINATED          0x22
-#define STS_TASK_SET_FULL               0x28
-#define    STS_QUEUE_FULL               0x28
-#define STS_ACA_ACTIVE                  0x30
-
-#define STS_VALID_MASK                  0x3e
-
-#define SCSI_STATUS(x)  ((x) & STS_VALID_MASK)
-
-/*
- *    SCSI QTag Types
- */
-#define QTAG_SIMPLE     0x20
-#define QTAG_HEAD_OF_Q  0x21
-#define QTAG_ORDERED    0x22
-
-/*
- *    SCSI Sense Key Definitons
- */
-#define SK_NO_SENSE         0x00
-#define SK_RECOVERED_ERROR  0x01
-#define SK_NOT_READY        0x02
-#define SK_MEDIUM_ERROR     0x03
-#define SK_HARDWARE_ERROR   0x04
-#define SK_ILLEGAL_REQUEST  0x05
-#define SK_UNIT_ATTENTION   0x06
-#define SK_DATA_PROTECT     0x07
-#define SK_BLANK_CHECK      0x08
-#define SK_VENDOR_SPECIFIC  0x09
-#define SK_COPY_ABORTED     0x0a
-#define SK_ABORTED_COMMAND  0x0b
-#define SK_EQUAL            0x0c
-#define SK_VOLUME_OVERFLOW  0x0d
-#define SK_MISCOMPARE       0x0e
-#define SK_RESERVED         0x0f
-
-
-
-#define SCSI_MAX_INQUIRY_BYTES  96
-#define SCSI_STD_INQUIRY_BYTES  36
-
-#undef USE_SCSI_COMPLETE_INQDATA
-/*
- *      Structure definition for SCSI Inquiry Data
- *
- *  NOTE: The following structure is 96 bytes in size
- *      iff USE_SCSI_COMPLETE_INQDATA IS defined above (i.e. w/ "#define").
- *      If USE_SCSI_COMPLETE_INQDATA is NOT defined above (i.e. w/ "#undef")
- *      then the following structure is only 36 bytes in size.
- *  THE CHOICE IS YOURS!
- */
-typedef struct SCSI_Inquiry_Data
-{
-#ifdef USE_SCSI_COMPLETE_INQDATA
-    u8   InqByte[SCSI_MAX_INQUIRY_BYTES];
-#else
-    u8   InqByte[SCSI_STD_INQUIRY_BYTES];
-#endif
-
-/*
- * the following structure works only for little-endian (Intel,
- * LSB first (1234) byte order) systems with 4-byte ints.
- *
-        u32    Periph_Device_Type    : 5,
-               Periph_Qualifier      : 3,
-               Device_Type_Modifier  : 7,
-               Removable_Media       : 1,
-               ANSI_Version          : 3,
-               ECMA_Version          : 3,
-               ISO_Version           : 2,
-               Response_Data_Format  : 4,
-               reserved_0            : 3,
-               AERC                  : 1  ;
-        u32    Additional_Length     : 8,
-               reserved_1            :16,
-               SftReset              : 1,
-               CmdQue                : 1,
-               reserved_2            : 1,
-               Linked                : 1,
-               Sync                  : 1,
-               WBus16                : 1,
-               WBus32                : 1,
-               RelAdr                : 1  ;
-        u8     Vendor_ID[8];
-        u8     Product_ID[16];
-        u8     Revision_Level [4];
-#ifdef USE_SCSI_COMPLETE_INQDATA
-        u8     Vendor_Specific[20];
-        u8     reserved_3[40];
-#endif
- *
- */
-
-} SCSI_Inquiry_Data_t;
-
-#define INQ_PERIPHINFO_BYTE            0
-#define   INQ_Periph_Qualifier_MASK      0xe0
-#define   INQ_Periph_Device_Type_MASK    0x1f
-
-#define INQ_Peripheral_Qualifier(inqp) \
-    (int)((*((u8*)(inqp)+INQ_PERIPHINFO_BYTE) & INQ_Periph_Qualifier_MASK) >> 5)
-#define INQ_Peripheral_Device_Type(inqp) \
-    (int)(*((u8*)(inqp)+INQ_PERIPHINFO_BYTE) & INQ_Periph_Device_Type_MASK)
-
-
-#define INQ_DEVTYPEMOD_BYTE            1
-#define   INQ_RMB_BIT                    0x80
-#define   INQ_Device_Type_Modifier_MASK  0x7f
-
-#define INQ_Removable_Medium(inqp) \
-    (int)(*((u8*)(inqp)+INQ_DEVTYPEMOD_BYTE) & INQ_RMB_BIT)
-#define INQ_Device_Type_Modifier(inqp) \
-    (int)(*((u8*)(inqp)+INQ_DEVTYPEMOD_BYTE) & INQ_Device_Type_Modifier_MASK)
-
-
-#define INQ_VERSIONINFO_BYTE           2
-#define   INQ_ISO_Version_MASK           0xc0
-#define   INQ_ECMA_Version_MASK          0x38
-#define   INQ_ANSI_Version_MASK          0x07
-
-#define INQ_ISO_Version(inqp) \
-    (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ISO_Version_MASK)
-#define INQ_ECMA_Version(inqp) \
-    (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ECMA_Version_MASK)
-#define INQ_ANSI_Version(inqp) \
-    (int)(*((u8*)(inqp)+INQ_VERSIONINFO_BYTE) & INQ_ANSI_Version_MASK)
-
-
-#define INQ_BYTE3                      3
-#define   INQ_AERC_BIT                   0x80
-#define   INQ_TrmTsk_BIT                 0x40
-#define   INQ_NormACA_BIT                0x20
-#define   INQ_RDF_MASK                   0x0F
-
-#define INQ_AER_Capable(inqp) \
-    (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_AERC_BIT)
-#define INQ_TrmTsk(inqp) \
-    (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_TrmTsk_BIT)
-#define INQ_NormACA(inqp) \
-    (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_NormACA_BIT)
-#define INQ_Response_Data_Format(inqp) \
-    (int)(*((u8*)(inqp)+INQ_BYTE3) & INQ_RDF_MASK)
-
-
-#define INQ_CAPABILITY_BYTE            7
-#define   INQ_RelAdr_BIT                 0x80
-#define   INQ_WBus32_BIT                 0x40
-#define   INQ_WBus16_BIT                 0x20
-#define   INQ_Sync_BIT                   0x10
-#define   INQ_Linked_BIT                 0x08
-  /*      INQ_Reserved BIT               0x40 */
-#define   INQ_CmdQue_BIT                 0x02
-#define   INQ_SftRe_BIT                  0x01
-
-#define IS_RelAdr_DEV(inqp) \
-    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_RelAdr_BIT)
-#define IS_WBus32_DEV(inqp) \
-    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_WBus32_BIT)
-#define IS_WBus16_DEV(inqp) \
-    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_WBus16_BIT)
-#define IS_Sync_DEV(inqp) \
-    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Sync_BIT)
-#define IS_Linked_DEV(inqp) \
-    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Linked_BIT)
-#define IS_CmdQue_DEV(inqp) \
-    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_CmdQue_BIT)
-#define IS_SftRe_DEV(inqp) \
-    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_SftRe_BIT)
-
-#define INQ_Width_BITS \
-    (INQ_WBus32_BIT | INQ_WBus16_BIT)
-#define IS_Wide_DEV(inqp) \
-    (int)(*((u8*)(inqp)+INQ_CAPABILITY_BYTE) & INQ_Width_BITS)
-
-
-/*
- *      SCSI peripheral device types
- */
-#define SCSI_TYPE_DAD               0x00  /* Direct Access Device */
-#define SCSI_TYPE_SAD               0x01  /* Sequential Access Device */
-#define SCSI_TYPE_TAPE  SCSI_TYPE_SAD
-#define SCSI_TYPE_PRT               0x02  /* Printer */
-#define SCSI_TYPE_PROC              0x03  /* Processor */
-#define SCSI_TYPE_WORM              0x04
-#define SCSI_TYPE_CDROM             0x05
-#define SCSI_TYPE_SCAN              0x06  /* Scanner */
-#define SCSI_TYPE_OPTICAL           0x07  /* Magneto/Optical */
-#define SCSI_TYPE_CHANGER           0x08
-#define SCSI_TYPE_COMM              0x09  /* Communications device */
-#define SCSI_TYPE_UNKNOWN           0x1f
-#define SCSI_TYPE_UNCONFIGURED_LUN  0x7f
-
-#define SCSI_TYPE_MAX_KNOWN         SCSI_TYPE_COMM
-
-/*
- *      Peripheral Qualifiers
- */
-#define DEVICE_PRESENT     0x00
-#define LUN_NOT_PRESENT    0x01
-#define LUN_NOT_SUPPORTED  0x03
-
-/*
- *      ANSI Versions
- */
-#ifndef SCSI_1
-#define SCSI_1  0x01
-#endif
-#ifndef SCSI_2
-#define SCSI_2  0x02
-#endif
-#ifndef SCSI_3
-#define SCSI_3  0x03
-#endif
-
-
-#define SCSI_MAX_SENSE_BYTES  255
-#define SCSI_STD_SENSE_BYTES   18
-#define SCSI_PAD_SENSE_BYTES      (SCSI_MAX_SENSE_BYTES - SCSI_STD_SENSE_BYTES)
-
-#undef USE_SCSI_COMPLETE_SENSE
-/*
- *      Structure definition for SCSI Sense Data
- *
- *  NOTE: The following structure is 255 bytes in size
- *      iiff USE_SCSI_COMPLETE_SENSE IS defined above (i.e. w/ "#define").
- *      If USE_SCSI_COMPLETE_SENSE is NOT defined above (i.e. w/ "#undef")
- *      then the following structure is only 19 bytes in size.
- *  THE CHOICE IS YOURS!
- *
- */
-typedef struct SCSI_Sense_Data
-{
-#ifdef USE_SCSI_COMPLETE_SENSE
-    u8       SenseByte[SCSI_MAX_SENSE_BYTES];
-#else
-    u8       SenseByte[SCSI_STD_SENSE_BYTES];
-#endif
-
-/*
- * the following structure works only for little-endian (Intel,
- * LSB first (1234) byte order) systems with 4-byte ints.
- *
-    u8     Error_Code                :4,            // 0x00
-           Error_Class               :3,
-           Valid                     :1
-     ;
-    u8     Segment_Number                           // 0x01
-     ;
-    u8     Sense_Key                 :4,            // 0x02
-           Reserved                  :1,
-           Incorrect_Length_Indicator:1,
-           End_Of_Media              :1,
-           Filemark                  :1
-     ;
-    u8     Information_MSB;                         // 0x03
-    u8     Information_Byte2;                       // 0x04
-    u8     Information_Byte1;                       // 0x05
-    u8     Information_LSB;                         // 0x06
-    u8     Additional_Length;                       // 0x07
-
-    u32    Command_Specific_Information;            // 0x08 - 0x0b
-
-    u8     Additional_Sense_Code;                   // 0x0c
-    u8     Additional_Sense_Code_Qualifier;         // 0x0d
-    u8     Field_Replaceable_Unit_Code;             // 0x0e
-    u8     Illegal_Req_Bit_Pointer   :3,            // 0x0f
-           Illegal_Req_Bit_Valid     :1,
-           Illegal_Req_Reserved      :2,
-           Illegal_Req_Cmd_Data      :1,
-           Sense_Key_Specific_Valid  :1
-     ;
-    u16    Sense_Key_Specific_Data;                 // 0x10 - 0x11
-
-#ifdef USE_SCSI_COMPLETE_SENSE
-    u8     Additional_Sense_Data[SCSI_PAD_SENSE_BYTES];
-#else
-    u8     Additional_Sense_Data[1];
-#endif
- *
- */
-
-} SCSI_Sense_Data_t;
-
-
-#define SD_ERRCODE_BYTE                0
-#define   SD_Valid_BIT                   0x80
-#define   SD_Error_Code_MASK             0x7f
-#define SD_Valid(sdp) \
-    (int)(*((u8*)(sdp)+SD_ERRCODE_BYTE) & SD_Valid_BIT)
-#define SD_Error_Code(sdp) \
-    (int)(*((u8*)(sdp)+SD_ERRCODE_BYTE) & SD_Error_Code_MASK)
-
-
-#define SD_SEGNUM_BYTE                 1
-#define SD_Segment_Number(sdp)  (int)(*((u8*)(sdp)+SD_SEGNUM_BYTE))
-
-
-#define SD_SENSEKEY_BYTE               2
-#define   SD_Filemark_BIT                0x80
-#define   SD_EOM_BIT                     0x40
-#define   SD_ILI_BIT                     0x20
-#define   SD_Sense_Key_MASK              0x0f
-#define SD_Filemark(sdp) \
-    (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_Filemark_BIT)
-#define SD_EOM(sdp) \
-    (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_EOM_BIT)
-#define SD_ILI(sdp) \
-    (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_ILI_BIT)
-#define SD_Sense_Key(sdp) \
-    (int)(*((u8*)(sdp)+SD_SENSEKEY_BYTE) & SD_Sense_Key_MASK)
-
-
-#define SD_INFO3_BYTE                  3
-#define SD_INFO2_BYTE                  4
-#define SD_INFO1_BYTE                  5
-#define SD_INFO0_BYTE                  6
-#define SD_Information3(sdp)  (int)(*((u8*)(sdp)+SD_INFO3_BYTE))
-#define SD_Information2(sdp)  (int)(*((u8*)(sdp)+SD_INFO2_BYTE))
-#define SD_Information1(sdp)  (int)(*((u8*)(sdp)+SD_INFO1_BYTE))
-#define SD_Information0(sdp)  (int)(*((u8*)(sdp)+SD_INFO0_BYTE))
-
-
-#define SD_ADDL_LEN_BYTE               7
-#define SD_Additional_Sense_Length(sdp) \
-    (int)(*((u8*)(sdp)+SD_ADDL_LEN_BYTE))
-#define SD_Addl_Sense_Len  SD_Additional_Sense_Length
-
-
-#define SD_CMD_SPECIFIC3_BYTE          8
-#define SD_CMD_SPECIFIC2_BYTE          9
-#define SD_CMD_SPECIFIC1_BYTE         10
-#define SD_CMD_SPECIFIC0_BYTE         11
-#define SD_Cmd_Specific_Info3(sdp)  (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC3_BYTE))
-#define SD_Cmd_Specific_Info2(sdp)  (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC2_BYTE))
-#define SD_Cmd_Specific_Info1(sdp)  (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC1_BYTE))
-#define SD_Cmd_Specific_Info0(sdp)  (int)(*((u8*)(sdp)+SD_CMD_SPECIFIC0_BYTE))
-
-
-#define SD_ADDL_SENSE_CODE_BYTE       12
-#define SD_Additional_Sense_Code(sdp) \
-    (int)(*((u8*)(sdp)+SD_ADDL_SENSE_CODE_BYTE))
-#define SD_Addl_Sense_Code  SD_Additional_Sense_Code
-#define SD_ASC  SD_Additional_Sense_Code
-
-
-#define SD_ADDL_SENSE_CODE_QUAL_BYTE  13
-#define SD_Additional_Sense_Code_Qualifier(sdp) \
-    (int)(*((u8*)(sdp)+SD_ADDL_SENSE_CODE_QUAL_BYTE))
-#define SD_Addl_Sense_Code_Qual  SD_Additional_Sense_Code_Qualifier
-#define SD_ASCQ  SD_Additional_Sense_Code_Qualifier
-
-
-#define SD_FIELD_REPL_UNIT_CODE_BYTE  14
-#define SD_Field_Replaceable_Unit_Code(sdp) \
-    (int)(*((u8*)(sdp)+SD_FIELD_REPL_UNIT_CODE_BYTE))
-#define SD_Field_Repl_Unit_Code  SD_Field_Replaceable_Unit_Code
-#define SD_FRUC  SD_Field_Replaceable_Unit_Code
-#define SD_FRU  SD_Field_Replaceable_Unit_Code
-
-
-/*
- *  Sense-Key Specific offsets and macros.
- */
-#define SD_SKS2_BYTE                  15
-#define   SD_SKS_Valid_BIT               0x80
-#define   SD_SKS_Cmd_Data_BIT            0x40
-#define   SD_SKS_Bit_Ptr_Valid_BIT       0x08
-#define   SD_SKS_Bit_Ptr_MASK            0x07
-#define SD_SKS1_BYTE                  16
-#define SD_SKS0_BYTE                  17
-#define SD_Sense_Key_Specific_Valid(sdp) \
-    (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Valid_BIT)
-#define SD_SKS_Valid  SD_Sense_Key_Specific_Valid
-#define SD_SKS_CDB_Error(sdp)  \
-    (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Cmd_Data_BIT)
-#define SD_Was_Illegal_Request  SD_SKS_CDB_Error
-#define SD_SKS_Bit_Pointer_Valid(sdp)  \
-    (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Bit_Ptr_Valid_BIT)
-#define SD_SKS_Bit_Pointer(sdp)  \
-    (int)(*((u8*)(sdp)+SD_SKS2_BYTE) & SD_SKS_Bit_Ptr_MASK)
-#define SD_Field_Pointer(sdp)  \
-    (int)( ((u16)(*((u8*)(sdp)+SD_SKS1_BYTE)) << 8) \
-      + *((u8*)(sdp)+SD_SKS0_BYTE) )
-#define SD_Bad_Byte  SD_Field_Pointer
-#define SD_Actual_Retry_Count  SD_Field_Pointer
-#define SD_Progress_Indication  SD_Field_Pointer
-
-/*
- *  Mode Sense Write Protect Mask
- */
-#define WRITE_PROTECT_MASK      0X80
-
-/*
- *  Medium Type Codes
- */
-#define OPTICAL_DEFAULT                 0x00
-#define OPTICAL_READ_ONLY_MEDIUM        0x01
-#define OPTICAL_WRITE_ONCE_MEDIUM       0x02
-#define OPTICAL_READ_WRITABLE_MEDIUM    0x03
-#define OPTICAL_RO_OR_WO_MEDIUM         0x04
-#define OPTICAL_RO_OR_RW_MEDIUM         0x05
-#define OPTICAL_WO_OR_RW_MEDIUM         0x06
-
-
-
-/*
- *    Structure definition for READ6, WRITE6 (6-byte CDB)
- */
-typedef struct SCSI_RW6_CDB
-{
-    u32    OpCode      :8,
-           LBA_HI      :5,    /* 5 MSBit's of the LBA */
-           Lun         :3,
-           LBA_MID     :8,    /* NOTE: total of 21 bits in LBA */
-           LBA_LO      :8  ;  /* Max LBA = 0x001fffff          */
-    u8     BlockCount;
-    u8     Control;
-} SCSI_RW6_t;
-
-#define MAX_RW6_LBA  ((u32)0x001fffff)
-
-/*
- *  Structure definition for READ10, WRITE10 (10-byte CDB)
- *
- *    NOTE: ParityCheck bit is applicable only for VERIFY and WRITE VERIFY for
- *    the ADP-92 DAC only.  In the SCSI2 spec. this same bit is defined as a
- *    FUA (forced unit access) bit for READs and WRITEs.  Since this driver
- *    does not use the FUA, this bit is defined as it is used by the ADP-92.
- *    Also, for READ CAPACITY, only the OpCode field is used.
- */
-typedef struct SCSI_RW10_CDB
-{
-    u8     OpCode;
-    u8     Reserved1;
-    u32    LBA;
-    u8     Reserved2;
-    u16    BlockCount;
-    u8     Control;
-} SCSI_RW10_t;
-
-#define PARITY_CHECK  0x08    /* parity check bit - byte[1], bit 3 */
-
-    /*
-     *  Structure definition for data returned by READ CAPACITY cmd;
-     *  READ CAPACITY data
-     */
-    typedef struct READ_CAP_DATA
-    {
-        u32    MaxLBA;
-        u32    BlockBytes;
-    } SCSI_READ_CAP_DATA_t, *pSCSI_READ_CAP_DATA_t;
-
-
-/*
- *  Structure definition for FORMAT UNIT CDB (6-byte CDB)
- */
-typedef struct _SCSI_FORMAT_UNIT
-{
-    u8     OpCode;
-    u8     Reserved1;
-    u8     VendorSpecific;
-    u16    Interleave;
-    u8     Control;
-} SCSI_FORMAT_UNIT_t;
-
-/*
- *    Structure definition for REQUEST SENSE (6-byte CDB)
- */
-typedef struct _SCSI_REQUEST_SENSE
-{
-    u8     OpCode;
-    u8     Reserved1;
-    u8     Reserved2;
-    u8     Reserved3;
-    u8     AllocLength;
-    u8     Control;
-} SCSI_REQ_SENSE_t;
-
-/*
- *  Structure definition for REPORT LUNS (12-byte CDB)
- */
-typedef struct _SCSI_REPORT_LUNS
-{
-    u8     OpCode;
-    u8     Reserved1[5];
-    u32    AllocationLength;
-    u8     Reserved2;
-    u8     Control;
-} SCSI_REPORT_LUNS_t, *pSCSI_REPORT_LUNS_t;
-
-    /*
-     *  (per-level) LUN information bytes
-     */
-/*
- *  Following doesn't work on ARMCC compiler
- *  [apparently] because it pads every struct
- *  to be multiple of 4 bytes!
- *  So SCSI_LUN_LEVELS_t winds up being 16
- *  bytes instead of 8!
- *
-    typedef struct LUN_INFO
-    {
-        u8     AddrMethod_plus_LunOrBusNumber;
-        u8     LunOrTarget;
-    } SCSI_LUN_INFO_t, *pSCSI_LUN_INFO_t;
-
-    typedef struct LUN_LEVELS
-    {
-        SCSI_LUN_INFO_t  LUN_0;
-        SCSI_LUN_INFO_t  LUN_1;
-        SCSI_LUN_INFO_t  LUN_2;
-        SCSI_LUN_INFO_t  LUN_3;
-    } SCSI_LUN_LEVELS_t, *pSCSI_LUN_LEVELS_t;
-*/
-    /*
-     *  All 4 levels (8 bytes) of LUN information
-     */
-    typedef struct LUN_LEVELS
-    {
-        u8     LVL1_AddrMethod_plus_LunOrBusNumber;
-        u8     LVL1_LunOrTarget;
-        u8     LVL2_AddrMethod_plus_LunOrBusNumber;
-        u8     LVL2_LunOrTarget;
-        u8     LVL3_AddrMethod_plus_LunOrBusNumber;
-        u8     LVL3_LunOrTarget;
-        u8     LVL4_AddrMethod_plus_LunOrBusNumber;
-        u8     LVL4_LunOrTarget;
-    } SCSI_LUN_LEVELS_t, *pSCSI_LUN_LEVELS_t;
-
-    /*
-     *  Structure definition for data returned by REPORT LUNS cmd;
-     *  LUN reporting parameter list format
-     */
-    typedef struct LUN_REPORT
-    {
-        u32                LunListLength;
-        u32                Reserved;
-        SCSI_LUN_LEVELS_t  LunInfo[1];
-    } SCSI_LUN_REPORT_t, *pSCSI_LUN_REPORT_t;
-
-/****************************************************************************
- *
- *  Externals
- */
-
-/****************************************************************************
- *
- *  Public Typedefs & Related Defines
- */
-
-/****************************************************************************
- *
- *  Macros (embedded, above)
- */
-
-/****************************************************************************
- *
- *  Public Variables
- */
-
-/****************************************************************************
- *
- *  Public Prototypes (module entry points)
- */
-
-
-/***************************************************************************/
-#endif
diff -Nru a/drivers/message/fusion/scsiops.c b/drivers/message/fusion/scsiops.c
--- a/drivers/message/fusion/scsiops.c	2002-02-05 11:10:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,309 +0,0 @@
-
-static const char *ScsiOpcodeString[256] = {
-	"TEST UNIT READY\0\01",				/* 00h */
-	"REWIND\0\002"
-		"\001REZERO UNIT",			/* 01h */
-	"\0\0",						/* 02h */
-	"REQUEST SENSE\0\01",				/* 03h */
-	"FORMAT UNIT\0\03"
-		"\001FORMAT MEDIUM\0"
-		"\002FORMAT",				/* 04h */
-	"READ BLOCK LIMITS\0\1",			/* 05h */
-	"\0\0",						/* 06h */
-	"REASSIGN BLOCKS\0\02"
-		"\010INITIALIZE ELEMENT STATUS",	/* 07h */
-	"READ(06)\0\04"
-		"\001READ\0"
-		"\003RECEIVE\0"
-		"\011GET MESSAGE(06)",			/* 08h */
-	"\0\0",						/* 09h */
-	"WRITE(06)\0\05"
-		"\001WRITE\0"
-		"\002PRINT\0"
-		"\003SEND(6)\0"
-		"\011SEND MESSAGE(06)",			/* 0Ah */
-	"SEEK(06)\0\02"
-		"\003SLEW AND PRINT",			/* 0Bh */
-	"\0\0",						/* 0Ch */
-	"\0\0",						/* 0Dh */
-	"\0\0",						/* 0Eh */
-	"READ REVERSE\0\01",				/* 0Fh */
-	"WRITE FILEMARKS\0\02"
-		"\003SYNCRONIZE BUFFER",		/* 10h */
-	"SPACE(6)\0\01",				/* 11h */
-	"INQUIRY\0\01",					/* 12h */
-	"VERIFY\0\01",					/* 13h */
-	"RECOVER BUFFERED DATA\0\01",			/* 14h */
-	"MODE SELECT(06)\0\01",				/* 15h */
-	"RESERVE(06)\0\02"
-		"\010RESERVE ELEMENT(06)",		/* 16h */
-	"RELEASE(06)\0\02"
-		"\010RELEASE ELEMENT(06)",		/* 17h */
-	"COPY\0\01",					/* 18h */
-	"ERASE\0\01",					/* 19h */
-	"MODE SENSE(06)\0\01",				/* 1Ah */
-	"STOP START UNIT\0\04"
-		"\001LOAD UNLOAD\0"
-		"\002STOP PRINT\0"
-		"\006SCAN\0\002",			/* 1Bh */
-	"RECEIVE DIAGNOSTIC RESULTS\0\01",		/* 1Ch */
-	"SEND DIAGNOSTIC\0\01",				/* 1Dh */
-	"PREVENT ALLOW MEDIUM REMOVAL\0\01",		/* 1Eh */
-	"\0\0",						/* 1Fh */
-	"\0\0",						/* 20h */
-	"\0\0",						/* 21h */
-	"\0\0",						/* 22h */
-	"READ FORMAT CAPACITIES\0\01",			/* 23h */
-	"SET WINDOW\0\01",				/* 24h */
-	"READ CAPACITY\0\03"
-		"\006GET WINDOW\0"
-		"\037FREAD CARD CAPACITY",		/* 25h */
-	"\0\0",						/* 26h */
-	"\0\0",						/* 27h */
-	"READ(10)\0\02"
-		"\011GET MESSAGE(10)",			/* 28h */
-	"READ GENERATION\0\01",				/* 29h */
-	"WRITE(10)\0\03"
-		"\011SEND(10)\0"
-		"\011SEND MESSAGE(10)",			/* 2Ah */
-	"SEEK(10)\0\03"
-		"LOCATE(10)\0"
-		"POSITION TO ELEMENT",			/* 2Bh */
-	"ERASE(10)\0\01",				/* 2Ch */
-	"READ UPDATED BLOCK\0\01",			/* 2Dh */
-	"WRITE AND VERIFY(10)\0\01",			/* 2Eh */
-	"VERIFY(10)\0\01",				/* 2Fh */
-	"SEARCH DATA HIGH(10)\0\01",			/* 30h */
-	"SEARCH DATA EQUAL(10)\0\02"
-		"OBJECT POSITION",			/* 31h */
-	"SEARCH DATA LOW(10)\0\01",			/* 32h */
-	"SET LIMITS(10)\0\01",				/* 33h */
-	"PRE-FETCH(10)\0\03"
-		"READ POSITION\0"
-		"GET DATA BUFFER STATUS",		/* 34h */
-	"SYNCHRONIZE CACHE(10)\0\01",			/* 35h */
-	"LOCK UNLOCK CACHE(10)\0\01",			/* 36h */
-	"READ DEFECT DATA(10)\0\01",			/* 37h */
-	"MEDIUM SCAN\0\01",				/* 38h */
-	"COMPARE\0\01",					/* 39h */
-	"COPY AND VERIFY\0\01",				/* 3Ah */
-	"WRITE BUFFER\0\01",				/* 3Bh */
-	"READ BUFFER\0\01",				/* 3Ch */
-	"UPDATE BLOCK\0\01",				/* 3Dh */
-	"READ LONG\0\01",				/* 3Eh */
-	"WRITE LONG\0\01",				/* 3Fh */
-	"CHANGE DEFINITION\0\01",			/* 40h */
-	"WRITE SAME(10)\0\01",				/* 41h */
-	"READ SUB-CHANNEL\0\01",			/* 42h */
-	"READ TOC/PMA/ATIP\0\01",			/* 43h */
-	"REPORT DENSITY SUPPORT\0\01",			/* 44h */
-	"READ HEADER\0\01",				/* 44h */
-	"PLAY AUDIO(10)\0\01",				/* 45h */
-	"GET CONFIGURATION\0\01",			/* 46h */
-	"PLAY AUDIO MSF\0\01",				/* 47h */
-	"PLAY AUDIO TRACK INDEX\0\01",			/* 48h */
-	"PLAY TRACK RELATIVE(10)\0\01",			/* 49h */
-	"GET EVENT STATUS NOTIFICATION\0\01",		/* 4Ah */
-	"PAUSE/RESUME\0\01",				/* 4Bh */
-	"LOG SELECT\0\01",				/* 4Ch */
-	"LOG SENSE\0\01",				/* 4Dh */
-	"STOP PLAY/SCAN\0\01",				/* 4Eh */
-	"\0\0",						/* 4Fh */
-	"XDWRITE(10)\0\01",				/* 50h */
-	"XPWRITE(10)\0\02"
-		"READ DISC INFORMATION",		/* 51h */
-	"XDREAD(10)\0\01"
-		"READ TRACK INFORMATION",		/* 52h */
-	"RESERVE TRACK\0\01",				/* 53h */
-	"SEND OPC INFORMATION\0\01",			/* 54h */
-	"MODE SELECT(10)\0\01",				/* 55h */
-	"RESERVE(10)\0\02"
-		"RESERVE ELEMENT(10)",			/* 56h */
-	"RELEASE(10)\0\02"
-		"RELEASE ELEMENT(10)",			/* 57h */
-	"REPAIR TRACK\0\01",				/* 58h */
-	"READ MASTER CUE\0\01",				/* 59h */
-	"MODE SENSE(10)\0\01",				/* 5Ah */
-	"CLOSE TRACK/SESSION\0\01",			/* 5Bh */
-	"READ BUFFER CAPACITY\0\01",			/* 5Ch */
-	"SEND CUE SHEET\0\01",				/* 5Dh */
-	"PERSISTENT RESERVE IN\0\01",			/* 5Eh */
-	"PERSISTENT RESERVE OUT\0\01",			/* 5Fh */
-	"\0\0",						/* 60h */
-	"\0\0",						/* 61h */
-	"\0\0",						/* 62h */
-	"\0\0",						/* 63h */
-	"\0\0",						/* 64h */
-	"\0\0",						/* 65h */
-	"\0\0",						/* 66h */
-	"\0\0",						/* 67h */
-	"\0\0",						/* 68h */
-	"\0\0",						/* 69h */
-	"\0\0",						/* 6Ah */
-	"\0\0",						/* 6Bh */
-	"\0\0",						/* 6Ch */
-	"\0\0",						/* 6Dh */
-	"\0\0",						/* 6Eh */
-	"\0\0",						/* 6Fh */
-	"\0\0",						/* 70h */
-	"\0\0",						/* 71h */
-	"\0\0",						/* 72h */
-	"\0\0",						/* 73h */
-	"\0\0",						/* 74h */
-	"\0\0",						/* 75h */
-	"\0\0",						/* 76h */
-	"\0\0",						/* 77h */
-	"\0\0",						/* 78h */
-	"\0\0",						/* 79h */
-	"\0\0",						/* 7Ah */
-	"\0\0",						/* 7Bh */
-	"\0\0",						/* 7Ch */
-	"\0\0",						/* 7Eh */
-	"\0\0",						/* 7Eh */
-	"\0\0",						/* 7Fh */
-	"XDWRITE EXTENDED(16)\0\01",			/* 80h */
-	"REBUILD(16)\0\01",				/* 81h */
-	"REGENERATE(16)\0\01",				/* 82h */
-	"EXTENDED COPY\0\01",				/* 83h */
-	"RECEIVE COPY RESULTS\0\01",			/* 84h */
-	"ACCESS CONTROL IN  [proposed]\0\01",		/* 86h */
-	"ACCESS CONTROL OUT  [proposed]\0\01",		/* 87h */
-	"READ(16)\0\01",				/* 88h */
-	"DEVICE LOCKS  [proposed]\0\01",		/* 89h */
-	"WRITE(16)\0\01",				/* 8Ah */
-	"\0\0",						/* 8Bh */
-	"READ ATTRIBUTES [proposed]\0\01",		/* 8Ch */
-	"WRITE ATTRIBUTES [proposed]\0\01",		/* 8Dh */
-	"WRITE AND VERIFY(16)\0\01",			/* 8Eh */
-	"VERIFY(16)\0\01",				/* 8Fh */
-	"PRE-FETCH(16)\0\01",				/* 90h */
-	"SYNCHRONIZE CACHE(16)\0\02"
-		"SPACE(16) [1]",			/* 91h */
-	"LOCK UNLOCK CACHE(16)\0\02"
-		"LOCATE(16) [1]",			/* 92h */
-	"WRITE SAME(16)\0\01",				/* 93h */
-	"[usage proposed by SCSI Socket Services project]\0\01",	/* 94h */
-	"[usage proposed by SCSI Socket Services project]\0\01",	/* 95h */
-	"[usage proposed by SCSI Socket Services project]\0\01",	/* 96h */
-	"[usage proposed by SCSI Socket Services project]\0\01",	/* 97h */
-	"MARGIN CONTROL [proposed]\0\01",		/* 98h */
-	"\0\0",						/* 99h */
-	"\0\0",						/* 9Ah */
-	"\0\0",						/* 9Bh */
-	"\0\0",						/* 9Ch */
-	"\0\0",						/* 9Dh */
-	"SERVICE ACTION IN [proposed]\0\01",		/* 9Eh */
-	"SERVICE ACTION OUT [proposed]\0\01",		/* 9Fh */
-	"REPORT LUNS\0\01",				/* A0h */
-	"BLANK\0\01",					/* A1h */
-	"SEND EVENT\0\01",				/* A2h */
-	"MAINTENANCE (IN)\0\02"
-		"SEND KEY",				/* A3h */
-	"MAINTENANCE (OUT)\0\02"
-		"REPORT KEY",				/* A4h */
-	"MOVE MEDIUM\0\02"
-		"PLAY AUDIO(12)",			/* A5h */
-	"EXCHANGE MEDIUM\0\02"
-		"LOAD/UNLOAD C/DVD",			/* A6h */
-	"MOVE MEDIUM ATTACHED\0\02"
-		"SET READ AHEAD\0\01",			/* A7h */
-	"READ(12)\0\02"
-		"GET MESSAGE(12)",			/* A8h */
-	"PLAY TRACK RELATIVE(12)\0\01",			/* A9h */
-	"WRITE(12)\0\02"
-		"SEND MESSAGE(12)",			/* AAh */
-	"\0\0",						/* ABh */
-	"ERASE(12)\0\02"
-		"GET PERFORMANCE",			/* ACh */
-	"READ DVD STRUCTURE\0\01",			/* ADh */
-	"WRITE AND VERIFY(12)\0\01",			/* AEh */
-	"VERIFY(12)\0\01",				/* AFh */
-	"SEARCH DATA HIGH(12)\0\01",			/* B0h */
-	"SEARCH DATA EQUAL(12)\0\01",			/* B1h */
-	"SEARCH DATA LOW(12)\0\01",			/* B2h */
-	"SET LIMITS(12)\0\01",				/* B3h */
-	"READ ELEMENT STATUS ATTACHED\0\01",		/* B4h */
-	"REQUEST VOLUME ELEMENT ADDRESS\0\01",		/* B5h */
-	"SEND VOLUME TAG\0\02"
-		"SET STREAMING",			/* B6h */
-	"READ DEFECT DATA(12)\0\01",			/* B7h */
-	"READ ELEMENT STATUS\0\01",			/* B8h */
-	"READ CD MSF\0\01",				/* B9h */
-	"REDUNDANCY GROUP (IN)\0\02"
-		"SCAN",					/* BAh */
-	"REDUNDANCY GROUP (OUT)\0\02"
-		"SET CD-ROM SPEED",			/* BBh */
-	"SPARE (IN)\0\02"
-		"PLAY CD",				/* BCh */
-	"SPARE (OUT)\0\02"
-		"MECHANISM STATUS",			/* BDh */
-	"VOLUME SET (IN)\0\02"
-		"READ CD",				/* BEh */
-	"VOLUME SET (OUT)\0\0\02"
-		"SEND DVD STRUCTURE",			/* BFh */
-	"\0\0",						/* C0h */
-	"\0\0",						/* C1h */
-	"\0\0",						/* C2h */
-	"\0\0",						/* C3h */
-	"\0\0",						/* C4h */
-	"\0\0",						/* C5h */
-	"\0\0",						/* C6h */
-	"\0\0",						/* C7h */
-	"\0\0",						/* C8h */
-	"\0\0",						/* C9h */
-	"\0\0",						/* CAh */
-	"\0\0",						/* CBh */
-	"\0\0",						/* CCh */
-	"\0\0",						/* CDh */
-	"\0\0",						/* CEh */
-	"\0\0",						/* CFh */
-	"\0\0",						/* D0h */
-	"\0\0",						/* D1h */
-	"\0\0",						/* D2h */
-	"\0\0",						/* D3h */
-	"\0\0",						/* D4h */
-	"\0\0",						/* D5h */
-	"\0\0",						/* D6h */
-	"\0\0",						/* D7h */
-	"\0\0",						/* D8h */
-	"\0\0",						/* D9h */
-	"\0\0",						/* DAh */
-	"\0\0",						/* DBh */
-	"\0\0",						/* DCh */
-	"\0\0",						/* DEh */
-	"\0\0",						/* DEh */
-	"\0\0",						/* DFh */
-	"\0\0",						/* E0h */
-	"\0\0",						/* E1h */
-	"\0\0",						/* E2h */
-	"\0\0",						/* E3h */
-	"\0\0",						/* E4h */
-	"\0\0",						/* E5h */
-	"\0\0",						/* E6h */
-	"\0\0",						/* E7h */
-	"\0\0",						/* E8h */
-	"\0\0",						/* E9h */
-	"\0\0",						/* EAh */
-	"\0\0",						/* EBh */
-	"\0\0",						/* ECh */
-	"\0\0",						/* EDh */
-	"\0\0",						/* EEh */
-	"\0\0",						/* EFh */
-	"\0\0",						/* F0h */
-	"\0\0",						/* F1h */
-	"\0\0",						/* F2h */
-	"\0\0",						/* F3h */
-	"\0\0",						/* F4h */
-	"\0\0",						/* F5h */
-	"\0\0",						/* F6h */
-	"\0\0",						/* F7h */
-	"\0\0",						/* F8h */
-	"\0\0",						/* F9h */
-	"\0\0",						/* FAh */
-	"\0\0",						/* FBh */
-	"\0\0",						/* FEh */
-	"\0\0",						/* FEh */
-	"\0\0",						/* FEh */
-	"\0\0"						/* FFh */
-};
-
diff -Nru a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile
--- a/drivers/message/i2o/Makefile	2004-05-14 19:00:14 -07:00
+++ b/drivers/message/i2o/Makefile	2004-08-24 11:29:24 -07:00
@@ -5,6 +5,7 @@
 # In the future, some of these should be built conditionally.
 #
 
+i2o_core-y		+= iop.o driver.o device.o debug.o pci.o exec-osm.o
 obj-$(CONFIG_I2O)	+= i2o_core.o
 obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o
 obj-$(CONFIG_I2O_BLOCK)	+= i2o_block.o
diff -Nru a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/message/i2o/debug.c	2004-08-24 11:29:28 -07:00
@@ -0,0 +1,571 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/i2o.h>
+
+static int verbose;
+extern struct i2o_driver **i2o_drivers;
+extern unsigned int i2o_max_drivers;
+static void i2o_report_util_cmd(u8 cmd);
+static void i2o_report_exec_cmd(u8 cmd);
+void i2o_report_fail_status(u8 req_status, u32 * msg);
+void i2o_report_common_status(u8 req_status);
+static void i2o_report_common_dsc(u16 detailed_status);
+
+void i2o_dump_status_block(i2o_status_block * sb)
+{
+	pr_debug("Organization ID: %d\n", sb->org_id);
+	pr_debug("IOP ID:          %d\n", sb->iop_id);
+	pr_debug("Host Unit ID:    %d\n", sb->host_unit_id);
+	pr_debug("Segment Number:  %d\n", sb->segment_number);
+	pr_debug("I2O Version:     %d\n", sb->i2o_version);
+	pr_debug("IOP State:       %d\n", sb->iop_state);
+	pr_debug("Messanger Type:  %d\n", sb->msg_type);
+	pr_debug("Inbound Frame Size:      %d\n", sb->inbound_frame_size);
+	pr_debug("Init Code:               %d\n", sb->init_code);
+	pr_debug("Max Inbound MFrames:     %d\n", sb->max_inbound_frames);
+	pr_debug("Current Inbound MFrames: %d\n", sb->cur_inbound_frames);
+	pr_debug("Max Outbound MFrames:    %d\n", sb->max_outbound_frames);
+	pr_debug("Product ID String: %s\n", sb->product_id);
+	pr_debug("Expected LCT Size: %d\n", sb->expected_lct_size);
+	pr_debug("IOP Capabilities:  %d\n", sb->iop_capabilities);
+	pr_debug("Desired Private MemSize: %d\n", sb->desired_mem_size);
+	pr_debug("Current Private MemSize: %d\n", sb->current_mem_size);
+	pr_debug("Current Private MemBase: %d\n", sb->current_mem_base);
+	pr_debug("Desired Private IO Size: %d\n", sb->desired_io_size);
+	pr_debug("Current Private IO Size: %d\n", sb->current_io_size);
+	pr_debug("Current Private IO Base: %d\n", sb->current_io_base);
+};
+
+/*
+ * Used for error reporting/debugging purposes.
+ * Report Cmd name, Request status, Detailed Status.
+ */
+void i2o_report_status(const char *severity, const char *str,
+		       struct i2o_message *m)
+{
+	u32 *msg = (u32 *) m;
+	u8 cmd = (msg[1] >> 24) & 0xFF;
+	u8 req_status = (msg[4] >> 24) & 0xFF;
+	u16 detailed_status = msg[4] & 0xFFFF;
+	//struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)];
+
+	if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
+		return;		// No status in this reply
+
+	printk("%s%s: ", severity, str);
+
+	if (cmd < 0x1F)		// Utility cmd
+		i2o_report_util_cmd(cmd);
+
+	else if (cmd >= 0xA0 && cmd <= 0xEF)	// Executive cmd
+		i2o_report_exec_cmd(cmd);
+	else
+		printk("Cmd = %0#2x, ", cmd);	// Other cmds
+
+	if (msg[0] & MSG_FAIL) {
+		i2o_report_fail_status(req_status, msg);
+		return;
+	}
+
+	i2o_report_common_status(req_status);
+
+	if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF))
+		i2o_report_common_dsc(detailed_status);
+	else
+		printk(" / DetailedStatus = %0#4x.\n", detailed_status);
+}
+
+/* Used to dump a message to syslog during debugging */
+void i2o_dump_message(struct i2o_message *m)
+{
+#ifdef DEBUG
+	u32 *msg = (u32 *) m;
+	int i;
+	printk(KERN_INFO "Dumping I2O message size %d @ %p\n",
+	       msg[0] >> 16 & 0xffff, msg);
+	for (i = 0; i < ((msg[0] >> 16) & 0xffff); i++)
+		printk(KERN_INFO "  msg[%d] = %0#10x\n", i, msg[i]);
+#endif
+}
+
+/**
+ *	i2o_report_controller_unit - print information about a tid
+ *	@c: controller
+ *	@d: device
+ *
+ *	Dump an information block associated with a given unit (TID). The
+ *	tables are read and a block of text is output to printk that is
+ *	formatted intended for the user.
+ */
+
+void i2o_report_controller_unit(struct i2o_controller *c, struct i2o_device *d)
+{
+	char buf[64];
+	char str[22];
+	int ret;
+
+	if (verbose == 0)
+		return;
+
+	printk(KERN_INFO "Target ID %03x.\n", d->lct_data.tid);
+	if ((ret = i2o_parm_field_get(d, 0xF100, 3, buf, 16)) >= 0) {
+		buf[16] = 0;
+		printk(KERN_INFO "     Vendor: %s\n", buf);
+	}
+	if ((ret = i2o_parm_field_get(d, 0xF100, 4, buf, 16)) >= 0) {
+		buf[16] = 0;
+		printk(KERN_INFO "     Device: %s\n", buf);
+	}
+	if (i2o_parm_field_get(d, 0xF100, 5, buf, 16) >= 0) {
+		buf[16] = 0;
+		printk(KERN_INFO "     Description: %s\n", buf);
+	}
+	if ((ret = i2o_parm_field_get(d, 0xF100, 6, buf, 8)) >= 0) {
+		buf[8] = 0;
+		printk(KERN_INFO "        Rev: %s\n", buf);
+	}
+
+	printk(KERN_INFO "    Class: ");
+	//sprintf(str, "%-21s", i2o_get_class_name(d->lct_data.class_id));
+	printk("%s\n", str);
+
+	printk(KERN_INFO "  Subclass: 0x%04X\n", d->lct_data.sub_class);
+	printk(KERN_INFO "     Flags: ");
+
+	if (d->lct_data.device_flags & (1 << 0))
+		printk("C");	// ConfigDialog requested
+	if (d->lct_data.device_flags & (1 << 1))
+		printk("U");	// Multi-user capable
+	if (!(d->lct_data.device_flags & (1 << 4)))
+		printk("P");	// Peer service enabled!
+	if (!(d->lct_data.device_flags & (1 << 5)))
+		printk("M");	// Mgmt service enabled!
+	printk("\n");
+}
+
+/*
+MODULE_PARM(verbose, "i");
+MODULE_PARM_DESC(verbose, "Verbose diagnostics");
+*/
+/*
+ * Used for error reporting/debugging purposes.
+ * Following fail status are common to all classes.
+ * The preserved message must be handled in the reply handler.
+ */
+void i2o_report_fail_status(u8 req_status, u32 * msg)
+{
+	static char *FAIL_STATUS[] = {
+		"0x80",		/* not used */
+		"SERVICE_SUSPENDED",	/* 0x81 */
+		"SERVICE_TERMINATED",	/* 0x82 */
+		"CONGESTION",
+		"FAILURE",
+		"STATE_ERROR",
+		"TIME_OUT",
+		"ROUTING_FAILURE",
+		"INVALID_VERSION",
+		"INVALID_OFFSET",
+		"INVALID_MSG_FLAGS",
+		"FRAME_TOO_SMALL",
+		"FRAME_TOO_LARGE",
+		"INVALID_TARGET_ID",
+		"INVALID_INITIATOR_ID",
+		"INVALID_INITIATOR_CONTEX",	/* 0x8F */
+		"UNKNOWN_FAILURE"	/* 0xFF */
+	};
+
+	if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
+		printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.", req_status);
+	else
+		printk("TRANSPORT_%s.\n", FAIL_STATUS[req_status & 0x0F]);
+
+	/* Dump some details */
+
+	printk(KERN_ERR "  InitiatorId = %d, TargetId = %d\n",
+	       (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF);
+	printk(KERN_ERR "  LowestVersion = 0x%02X, HighestVersion = 0x%02X\n",
+	       (msg[4] >> 8) & 0xFF, msg[4] & 0xFF);
+	printk(KERN_ERR "  FailingHostUnit = 0x%04X,  FailingIOP = 0x%03X\n",
+	       msg[5] >> 16, msg[5] & 0xFFF);
+
+	printk(KERN_ERR "  Severity:  0x%02X ", (msg[4] >> 16) & 0xFF);
+	if (msg[4] & (1 << 16))
+		printk("(FormatError), "
+		       "this msg can never be delivered/processed.\n");
+	if (msg[4] & (1 << 17))
+		printk("(PathError), "
+		       "this msg can no longer be delivered/processed.\n");
+	if (msg[4] & (1 << 18))
+		printk("(PathState), "
+		       "the system state does not allow delivery.\n");
+	if (msg[4] & (1 << 19))
+		printk("(Congestion), resources temporarily not available;"
+		       "do not retry immediately.\n");
+}
+
+/*
+ * Used for error reporting/debugging purposes.
+ * Following reply status are common to all classes.
+ */
+void i2o_report_common_status(u8 req_status)
+{
+	static char *REPLY_STATUS[] = {
+		"SUCCESS",
+		"ABORT_DIRTY",
+		"ABORT_NO_DATA_TRANSFER",
+		"ABORT_PARTIAL_TRANSFER",
+		"ERROR_DIRTY",
+		"ERROR_NO_DATA_TRANSFER",
+		"ERROR_PARTIAL_TRANSFER",
+		"PROCESS_ABORT_DIRTY",
+		"PROCESS_ABORT_NO_DATA_TRANSFER",
+		"PROCESS_ABORT_PARTIAL_TRANSFER",
+		"TRANSACTION_ERROR",
+		"PROGRESS_REPORT"
+	};
+
+	if (req_status >= ARRAY_SIZE(REPLY_STATUS))
+		printk("RequestStatus = %0#2x", req_status);
+	else
+		printk("%s", REPLY_STATUS[req_status]);
+}
+
+/*
+ * Used for error reporting/debugging purposes.
+ * Following detailed status are valid  for executive class,
+ * utility class, DDM class and for transaction error replies.
+ */
+static void i2o_report_common_dsc(u16 detailed_status)
+{
+	static char *COMMON_DSC[] = {
+		"SUCCESS",
+		"0x01",		// not used
+		"BAD_KEY",
+		"TCL_ERROR",
+		"REPLY_BUFFER_FULL",
+		"NO_SUCH_PAGE",
+		"INSUFFICIENT_RESOURCE_SOFT",
+		"INSUFFICIENT_RESOURCE_HARD",
+		"0x08",		// not used
+		"CHAIN_BUFFER_TOO_LARGE",
+		"UNSUPPORTED_FUNCTION",
+		"DEVICE_LOCKED",
+		"DEVICE_RESET",
+		"INAPPROPRIATE_FUNCTION",
+		"INVALID_INITIATOR_ADDRESS",
+		"INVALID_MESSAGE_FLAGS",
+		"INVALID_OFFSET",
+		"INVALID_PARAMETER",
+		"INVALID_REQUEST",
+		"INVALID_TARGET_ADDRESS",
+		"MESSAGE_TOO_LARGE",
+		"MESSAGE_TOO_SMALL",
+		"MISSING_PARAMETER",
+		"TIMEOUT",
+		"UNKNOWN_ERROR",
+		"UNKNOWN_FUNCTION",
+		"UNSUPPORTED_VERSION",
+		"DEVICE_BUSY",
+		"DEVICE_NOT_AVAILABLE"
+	};
+
+	if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE)
+		printk(" / DetailedStatus = %0#4x.\n", detailed_status);
+	else
+		printk(" / %s.\n", COMMON_DSC[detailed_status]);
+}
+
+/*
+ * Used for error reporting/debugging purposes
+ */
+static void i2o_report_util_cmd(u8 cmd)
+{
+	switch (cmd) {
+	case I2O_CMD_UTIL_NOP:
+		printk("UTIL_NOP, ");
+		break;
+	case I2O_CMD_UTIL_ABORT:
+		printk("UTIL_ABORT, ");
+		break;
+	case I2O_CMD_UTIL_CLAIM:
+		printk("UTIL_CLAIM, ");
+		break;
+	case I2O_CMD_UTIL_RELEASE:
+		printk("UTIL_CLAIM_RELEASE, ");
+		break;
+	case I2O_CMD_UTIL_CONFIG_DIALOG:
+		printk("UTIL_CONFIG_DIALOG, ");
+		break;
+	case I2O_CMD_UTIL_DEVICE_RESERVE:
+		printk("UTIL_DEVICE_RESERVE, ");
+		break;
+	case I2O_CMD_UTIL_DEVICE_RELEASE:
+		printk("UTIL_DEVICE_RELEASE, ");
+		break;
+	case I2O_CMD_UTIL_EVT_ACK:
+		printk("UTIL_EVENT_ACKNOWLEDGE, ");
+		break;
+	case I2O_CMD_UTIL_EVT_REGISTER:
+		printk("UTIL_EVENT_REGISTER, ");
+		break;
+	case I2O_CMD_UTIL_LOCK:
+		printk("UTIL_LOCK, ");
+		break;
+	case I2O_CMD_UTIL_LOCK_RELEASE:
+		printk("UTIL_LOCK_RELEASE, ");
+		break;
+	case I2O_CMD_UTIL_PARAMS_GET:
+		printk("UTIL_PARAMS_GET, ");
+		break;
+	case I2O_CMD_UTIL_PARAMS_SET:
+		printk("UTIL_PARAMS_SET, ");
+		break;
+	case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY:
+		printk("UTIL_REPLY_FAULT_NOTIFY, ");
+		break;
+	default:
+		printk("Cmd = %0#2x, ", cmd);
+	}
+}
+
+/*
+ * Used for error reporting/debugging purposes
+ */
+static void i2o_report_exec_cmd(u8 cmd)
+{
+	switch (cmd) {
+	case I2O_CMD_ADAPTER_ASSIGN:
+		printk("EXEC_ADAPTER_ASSIGN, ");
+		break;
+	case I2O_CMD_ADAPTER_READ:
+		printk("EXEC_ADAPTER_READ, ");
+		break;
+	case I2O_CMD_ADAPTER_RELEASE:
+		printk("EXEC_ADAPTER_RELEASE, ");
+		break;
+	case I2O_CMD_BIOS_INFO_SET:
+		printk("EXEC_BIOS_INFO_SET, ");
+		break;
+	case I2O_CMD_BOOT_DEVICE_SET:
+		printk("EXEC_BOOT_DEVICE_SET, ");
+		break;
+	case I2O_CMD_CONFIG_VALIDATE:
+		printk("EXEC_CONFIG_VALIDATE, ");
+		break;
+	case I2O_CMD_CONN_SETUP:
+		printk("EXEC_CONN_SETUP, ");
+		break;
+	case I2O_CMD_DDM_DESTROY:
+		printk("EXEC_DDM_DESTROY, ");
+		break;
+	case I2O_CMD_DDM_ENABLE:
+		printk("EXEC_DDM_ENABLE, ");
+		break;
+	case I2O_CMD_DDM_QUIESCE:
+		printk("EXEC_DDM_QUIESCE, ");
+		break;
+	case I2O_CMD_DDM_RESET:
+		printk("EXEC_DDM_RESET, ");
+		break;
+	case I2O_CMD_DDM_SUSPEND:
+		printk("EXEC_DDM_SUSPEND, ");
+		break;
+	case I2O_CMD_DEVICE_ASSIGN:
+		printk("EXEC_DEVICE_ASSIGN, ");
+		break;
+	case I2O_CMD_DEVICE_RELEASE:
+		printk("EXEC_DEVICE_RELEASE, ");
+		break;
+	case I2O_CMD_HRT_GET:
+		printk("EXEC_HRT_GET, ");
+		break;
+	case I2O_CMD_ADAPTER_CLEAR:
+		printk("EXEC_IOP_CLEAR, ");
+		break;
+	case I2O_CMD_ADAPTER_CONNECT:
+		printk("EXEC_IOP_CONNECT, ");
+		break;
+	case I2O_CMD_ADAPTER_RESET:
+		printk("EXEC_IOP_RESET, ");
+		break;
+	case I2O_CMD_LCT_NOTIFY:
+		printk("EXEC_LCT_NOTIFY, ");
+		break;
+	case I2O_CMD_OUTBOUND_INIT:
+		printk("EXEC_OUTBOUND_INIT, ");
+		break;
+	case I2O_CMD_PATH_ENABLE:
+		printk("EXEC_PATH_ENABLE, ");
+		break;
+	case I2O_CMD_PATH_QUIESCE:
+		printk("EXEC_PATH_QUIESCE, ");
+		break;
+	case I2O_CMD_PATH_RESET:
+		printk("EXEC_PATH_RESET, ");
+		break;
+	case I2O_CMD_STATIC_MF_CREATE:
+		printk("EXEC_STATIC_MF_CREATE, ");
+		break;
+	case I2O_CMD_STATIC_MF_RELEASE:
+		printk("EXEC_STATIC_MF_RELEASE, ");
+		break;
+	case I2O_CMD_STATUS_GET:
+		printk("EXEC_STATUS_GET, ");
+		break;
+	case I2O_CMD_SW_DOWNLOAD:
+		printk("EXEC_SW_DOWNLOAD, ");
+		break;
+	case I2O_CMD_SW_UPLOAD:
+		printk("EXEC_SW_UPLOAD, ");
+		break;
+	case I2O_CMD_SW_REMOVE:
+		printk("EXEC_SW_REMOVE, ");
+		break;
+	case I2O_CMD_SYS_ENABLE:
+		printk("EXEC_SYS_ENABLE, ");
+		break;
+	case I2O_CMD_SYS_MODIFY:
+		printk("EXEC_SYS_MODIFY, ");
+		break;
+	case I2O_CMD_SYS_QUIESCE:
+		printk("EXEC_SYS_QUIESCE, ");
+		break;
+	case I2O_CMD_SYS_TAB_SET:
+		printk("EXEC_SYS_TAB_SET, ");
+		break;
+	default:
+		printk("Cmd = %#02x, ", cmd);
+	}
+}
+
+void i2o_debug_state(struct i2o_controller *c)
+{
+	printk(KERN_INFO "%s: State = ", c->name);
+	switch (((i2o_status_block *) c->status_block.virt)->iop_state) {
+	case 0x01:
+		printk("INIT\n");
+		break;
+	case 0x02:
+		printk("RESET\n");
+		break;
+	case 0x04:
+		printk("HOLD\n");
+		break;
+	case 0x05:
+		printk("READY\n");
+		break;
+	case 0x08:
+		printk("OPERATIONAL\n");
+		break;
+	case 0x10:
+		printk("FAILED\n");
+		break;
+	case 0x11:
+		printk("FAULTED\n");
+		break;
+	default:
+		printk("%x (unknown !!)\n",
+		       ((i2o_status_block *) c->status_block.virt)->iop_state);
+	}
+};
+
+void i2o_systab_debug(struct i2o_sys_tbl *sys_tbl)
+{
+	u32 *table;
+	int count;
+	u32 size;
+
+	table = (u32 *) sys_tbl;
+	size = sizeof(struct i2o_sys_tbl) + sys_tbl->num_entries
+	    * sizeof(struct i2o_sys_tbl_entry);
+
+	for (count = 0; count < (size >> 2); count++)
+		printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]);
+}
+
+void i2o_dump_hrt(struct i2o_controller *c)
+{
+	u32 *rows = (u32 *) c->hrt.virt;
+	u8 *p = (u8 *) c->hrt.virt;
+	u8 *d;
+	int count;
+	int length;
+	int i;
+	int state;
+
+	if (p[3] != 0) {
+		printk(KERN_ERR
+		       "%s: HRT table for controller is too new a version.\n",
+		       c->name);
+		return;
+	}
+
+	count = p[0] | (p[1] << 8);
+	length = p[2];
+
+	printk(KERN_INFO "%s: HRT has %d entries of %d bytes each.\n",
+	       c->name, count, length << 2);
+
+	rows += 2;
+
+	for (i = 0; i < count; i++) {
+		printk(KERN_INFO "Adapter %08X: ", rows[0]);
+		p = (u8 *) (rows + 1);
+		d = (u8 *) (rows + 2);
+		state = p[1] << 8 | p[0];
+
+		printk("TID %04X:[", state & 0xFFF);
+		state >>= 12;
+		if (state & (1 << 0))
+			printk("H");	/* Hidden */
+		if (state & (1 << 2)) {
+			printk("P");	/* Present */
+			if (state & (1 << 1))
+				printk("C");	/* Controlled */
+		}
+		if (state > 9)
+			printk("*");	/* Hard */
+
+		printk("]:");
+
+		switch (p[3] & 0xFFFF) {
+		case 0:
+			/* Adapter private bus - easy */
+			printk("Local bus %d: I/O at 0x%04X Mem 0x%08X",
+			       p[2], d[1] << 8 | d[0], *(u32 *) (d + 4));
+			break;
+		case 1:
+			/* ISA bus */
+			printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X",
+			       p[2], d[2], d[1] << 8 | d[0], *(u32 *) (d + 4));
+			break;
+
+		case 2:	/* EISA bus */
+			printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X",
+			       p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4));
+			break;
+
+		case 3:	/* MCA bus */
+			printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X",
+			       p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4));
+			break;
+
+		case 4:	/* PCI bus */
+			printk("PCI %d: Bus %d Device %d Function %d",
+			       p[2], d[2], d[1], d[0]);
+			break;
+
+		case 0x80:	/* Other */
+		default:
+			printk("Unsupported bus type.");
+			break;
+		}
+		printk("\n");
+		rows += length;
+	}
+}
+
+EXPORT_SYMBOL(i2o_dump_status_block);
+EXPORT_SYMBOL(i2o_dump_message);
diff -Nru a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/message/i2o/device.c	2004-08-19 09:24:16 -07:00
@@ -0,0 +1,674 @@
+/*
+ *	Functions to handle I2O devices
+ *
+ *	Copyright (C) 2004	Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *
+ *	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 of the License, or (at your
+ *	option) any later version.
+ *
+ *	Fixes/additions:
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *			initial version.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+
+/* Exec OSM functions */
+extern struct bus_type i2o_bus_type;
+
+/**
+ *	i2o_device_issue_claim - claim or release a device
+ *	@dev: I2O device to claim or release
+ *	@cmd: claim or release command
+ *	@type: type of claim
+ *
+ *	Issue I2O UTIL_CLAIM or UTIL_RELEASE messages. The message to be sent
+ *	is set by cmd. dev is the I2O device which should be claim or
+ *	released and the type is the claim type (see the I2O spec).
+ *
+ *	Returs 0 on success or negative error code on failure.
+ */
+static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
+					 u32 type)
+{
+	struct i2o_message *msg;
+	u32 m;
+
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid, &msg->u.head[1]);
+	writel(type, &msg->body[0]);
+
+	return i2o_msg_post_wait(dev->iop, m, 60);
+};
+
+/**
+ * 	i2o_device_claim - claim a device for use by an OSM
+ *	@dev: I2O device to claim
+ *	@drv: I2O driver which wants to claim the device
+ *
+ *	Do the leg work to assign a device to a given OSM. If the claim succeed
+ *	the owner of the rimary. If the attempt fails a negative errno code
+ *	is returned. On success zero is returned.
+ */
+int i2o_device_claim(struct i2o_device *dev)
+{
+	int rc = 0;
+
+	down(&dev->lock);
+
+	rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);
+	if (!rc)
+		pr_debug("claim of device %d succeded\n", dev->lct_data.tid);
+	else
+		pr_debug("claim of device %d failed %d\n", dev->lct_data.tid,
+			 rc);
+
+	up(&dev->lock);
+
+	return rc;
+};
+
+/**
+ *	i2o_device_claim_release - release a device that the OSM is using
+ *	@dev: device to release
+ *	@drv: driver which claimed the device
+ *
+ *	Drop a claim by an OSM on a given I2O device.
+ *
+ *	AC - some devices seem to want to refuse an unclaim until they have
+ *	finished internal processing. It makes sense since you don't want a
+ *	new device to go reconfiguring the entire system until you are done.
+ *	Thus we are prepared to wait briefly.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int i2o_device_claim_release(struct i2o_device *dev)
+{
+	int tries;
+	int rc = 0;
+
+	down(&dev->lock);
+
+	/*
+	 *      If the controller takes a nonblocking approach to
+	 *      releases we have to sleep/poll for a few times.
+	 */
+	for (tries = 0; tries < 10; tries++) {
+		rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_RELEASE,
+					    I2O_CLAIM_PRIMARY);
+		if (!rc)
+			break;
+
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ);
+	}
+
+	if (!rc)
+		pr_debug("claim release of device %d succeded\n",
+			 dev->lct_data.tid);
+	else
+		pr_debug("claim release of device %d failed %d\n",
+			 dev->lct_data.tid, rc);
+
+	up(&dev->lock);
+
+	return rc;
+};
+
+/**
+ *	i2o_device_release - release the memory for a I2O device
+ *	@dev: I2O device which should be released
+ *
+ *	Release the allocated memory. This function is called if refcount of
+ *	device reaches 0 automatically.
+ */
+static void i2o_device_release(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+
+	pr_debug("Release I2O device %s\n", dev->bus_id);
+
+	kfree(i2o_dev);
+};
+
+/**
+ *	i2o_device_class_release - Remove I2O device attributes
+ *	@cd: I2O class device which is added to the I2O device class
+ *
+ *	Removes attributes from the I2O device again. Also search each device
+ *	on the controller for I2O devices which refert to this device as parent
+ *	or user and remove this links also.
+ */
+static void i2o_device_class_release(struct class_device *cd)
+{
+	struct i2o_device *i2o_dev, *tmp;
+	struct i2o_controller *c;
+
+	i2o_dev = to_i2o_device(cd->dev);
+	c = i2o_dev->iop;
+
+	sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+	sysfs_remove_link(&i2o_dev->device.kobj, "user");
+
+	list_for_each_entry(tmp, &c->devices, list) {
+		if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+			sysfs_remove_link(&tmp->device.kobj, "parent");
+		if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+			sysfs_remove_link(&tmp->device.kobj, "user");
+	}
+};
+
+/* I2O device class */
+static struct class i2o_device_class = {
+	.name = "i2o_device",
+	.release = i2o_device_class_release
+};
+
+/**
+ *	i2o_device_alloc - Allocate a I2O device and initialize it
+ *
+ *	Allocate the memory for a I2O device and initialize locks and lists
+ *
+ *	Returns the allocated I2O device or a negative error code if the device
+ *	could not be allocated.
+ */
+static struct i2o_device *i2o_device_alloc(void)
+{
+	struct i2o_device *dev;
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	memset(dev, 0, sizeof(*dev));
+
+	INIT_LIST_HEAD(&dev->list);
+	init_MUTEX(&dev->lock);
+
+	dev->device.bus = &i2o_bus_type;
+	dev->device.release = &i2o_device_release;
+	dev->classdev.class = &i2o_device_class;
+	dev->classdev.dev = &dev->device;
+
+	return dev;
+};
+
+/**
+ *	i2o_device_add - allocate a new I2O device and add it to the IOP
+ *	@iop: I2O controller where the device is on
+ *	@entry: LCT entry of the I2O device
+ *
+ *	Allocate a new I2O device and initialize it with the LCT entry. The
+ *	device is appended to the device list of the controller.
+ *
+ *	Returns a pointer to the I2O device on success or negative error code
+ *	on failure.
+ */
+struct i2o_device *i2o_device_add(struct i2o_controller *c,
+				  i2o_lct_entry * entry)
+{
+	struct i2o_device *dev;
+
+	dev = i2o_device_alloc();
+	if (IS_ERR(dev)) {
+		printk(KERN_ERR "i2o: unable to allocate i2o device\n");
+		return dev;
+	}
+
+	dev->lct_data = *entry;
+
+	snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
+		 dev->lct_data.tid);
+
+	snprintf(dev->classdev.class_id, BUS_ID_SIZE, "%d:%03x", c->unit,
+		 dev->lct_data.tid);
+
+	dev->iop = c;
+	dev->device.parent = &c->device;
+
+	device_register(&dev->device);
+
+	list_add_tail(&dev->list, &c->devices);
+
+	class_device_register(&dev->classdev);
+
+	i2o_driver_notify_device_add_all(dev);
+
+	pr_debug("I2O device %s added\n", dev->device.bus_id);
+
+	return dev;
+};
+
+/**
+ *	i2o_device_remove - remove an I2O device from the I2O core
+ *	@dev: I2O device which should be released
+ *
+ *	Is used on I2O controller removal or LCT modification, when the device
+ *	is removed from the system. Note that the device could still hang
+ *	around until the refcount reaches 0.
+ */
+void i2o_device_remove(struct i2o_device *i2o_dev)
+{
+	i2o_driver_notify_device_remove_all(i2o_dev);
+	class_device_unregister(&i2o_dev->classdev);
+	list_del(&i2o_dev->list);
+	device_unregister(&i2o_dev->device);
+};
+
+/**
+ *	i2o_device_parse_lct - Parse a previously fetched LCT and create devices
+ *	@c: I2O controller from which the LCT should be parsed.
+ *
+ *	The Logical Configuration Table tells us what we can talk to on the
+ *	board. For every entry we create an I2O device, which is registered in
+ *	the I2O core.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int i2o_device_parse_lct(struct i2o_controller *c)
+{
+	struct i2o_device *dev, *tmp;
+	i2o_lct *lct;
+	int i;
+	int max;
+
+	down(&c->lct_lock);
+
+	if (c->lct)
+		kfree(c->lct);
+
+	lct = c->dlct.virt;
+
+	c->lct = kmalloc(lct->table_size * 4, GFP_KERNEL);
+	if (!c->lct) {
+		up(&c->lct_lock);
+		return -ENOMEM;
+	}
+
+	if (lct->table_size * 4 > c->dlct.len) {
+		memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len);
+		up(&c->lct_lock);
+		return -EAGAIN;
+	}
+
+	memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4);
+
+	lct = c->lct;
+
+	max = (lct->table_size - 3) / 9;
+
+	pr_debug("LCT has %d entries (LCT size: %d)\n", max, lct->table_size);
+
+	/* remove devices, which are not in the LCT anymore */
+	list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+		int found = 0;
+
+		for (i = 0; i < max; i++) {
+			if (lct->lct_entry[i].tid == dev->lct_data.tid) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (!found)
+			i2o_device_remove(dev);
+	}
+
+	/* add new devices, which are new in the LCT */
+	for (i = 0; i < max; i++) {
+		int found = 0;
+
+		list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+			if (lct->lct_entry[i].tid == dev->lct_data.tid) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (!found)
+			i2o_device_add(c, &lct->lct_entry[i]);
+	}
+	up(&c->lct_lock);
+
+	return 0;
+};
+
+/**
+ *	i2o_device_class_show_class_id - Displays class id of I2O device
+ *	@cd: class device of which the class id should be displayed
+ *	@buf: buffer into which the class id should be printed
+ *
+ *	Returns the number of bytes which are printed into the buffer.
+ */
+static ssize_t i2o_device_class_show_class_id(struct class_device *cd,
+					      char *buf)
+{
+	struct i2o_device *dev = to_i2o_device(cd->dev);
+
+	sprintf(buf, "%03x\n", dev->lct_data.class_id);
+	return strlen(buf) + 1;
+};
+
+/**
+ *	i2o_device_class_show_tid - Displays TID of I2O device
+ *	@cd: class device of which the TID should be displayed
+ *	@buf: buffer into which the class id should be printed
+ *
+ *	Returns the number of bytes which are printed into the buffer.
+ */
+static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf)
+{
+	struct i2o_device *dev = to_i2o_device(cd->dev);
+
+	sprintf(buf, "%03x\n", dev->lct_data.tid);
+	return strlen(buf) + 1;
+};
+
+/* I2O device class attributes */
+static CLASS_DEVICE_ATTR(class_id, S_IRUGO, i2o_device_class_show_class_id,
+			 NULL);
+static CLASS_DEVICE_ATTR(tid, S_IRUGO, i2o_device_class_show_tid, NULL);
+
+/**
+ *	i2o_device_class_add - Adds attributes to the I2O device
+ *	@cd: I2O class device which is added to the I2O device class
+ *
+ *	This function get called when a I2O device is added to the class. It
+ *	creates the attributes for each device and creates user/parent symlink
+ *	if necessary.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_device_class_add(struct class_device *cd)
+{
+	struct i2o_device *i2o_dev, *tmp;
+	struct i2o_controller *c;
+
+	i2o_dev = to_i2o_device(cd->dev);
+	c = i2o_dev->iop;
+
+	class_device_create_file(cd, &class_device_attr_class_id);
+	class_device_create_file(cd, &class_device_attr_tid);
+
+	/* create user entries for this device */
+	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
+	if (tmp)
+		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+				  "user");
+
+	/* create user entries refering to this device */
+	list_for_each_entry(tmp, &c->devices, list)
+	    if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+		sysfs_create_link(&tmp->device.kobj,
+				  &i2o_dev->device.kobj, "user");
+
+	/* create parent entries for this device */
+	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
+	if (tmp)
+		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+				  "parent");
+
+	/* create parent entries refering to this device */
+	list_for_each_entry(tmp, &c->devices, list)
+	    if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+		sysfs_create_link(&tmp->device.kobj,
+				  &i2o_dev->device.kobj, "parent");
+
+	return 0;
+};
+
+/* I2O device class interface */
+static struct class_interface i2o_device_class_interface = {
+	.class = &i2o_device_class,
+	.add = i2o_device_class_add
+};
+
+/*
+ *	Run time support routines
+ */
+
+/*	Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
+ *
+ *	This function can be used for all UtilParamsGet/Set operations.
+ *	The OperationList is given in oplist-buffer,
+ *	and results are returned in reslist-buffer.
+ *	Note that the minimum sized reslist is 8 bytes and contains
+ *	ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
+ */
+
+int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
+		   int oplen, void *reslist, int reslen)
+{
+	struct i2o_message *msg;
+	u32 m;
+	u32 *res32 = (u32 *) reslist;
+	u32 *restmp = (u32 *) reslist;
+	int len = 0;
+	int i = 0;
+	int rc;
+	struct i2o_dma res;
+	struct i2o_controller *c = i2o_dev->iop;
+	struct device *dev = &c->pdev->dev;
+
+	res.virt = NULL;
+
+	if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL))
+		return -ENOMEM;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY) {
+		i2o_dma_free(dev, &res);
+		return -ETIMEDOUT;
+	}
+
+	i = 0;
+	writel(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(0, &msg->body[i++]);
+	writel(0x4C000000 | oplen, &msg->body[i++]);	/* OperationList */
+	memcpy_toio(&msg->body[i], oplist, oplen);
+	i += (oplen / 4 + (oplen % 4 ? 1 : 0));
+	writel(0xD0000000 | res.len, &msg->body[i++]);	/* ResultList */
+	writel(res.phys, &msg->body[i++]);
+
+	writel(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
+	       SGL_OFFSET_5, &msg->u.head[0]);
+
+	rc = i2o_msg_post_wait_mem(c, m, 10, &res);
+
+	/* This only looks like a memory leak - don't "fix" it. */
+	if (rc == -ETIMEDOUT)
+		return rc;
+
+	memcpy_fromio(reslist, res.virt, res.len);
+	i2o_dma_free(dev, &res);
+
+	/* Query failed */
+	if (rc)
+		return rc;
+	/*
+	 * Calculate number of bytes of Result LIST
+	 * We need to loop through each Result BLOCK and grab the length
+	 */
+	restmp = res32 + 1;
+	len = 1;
+	for (i = 0; i < (res32[0] & 0X0000FFFF); i++) {
+		if (restmp[0] & 0x00FF0000) {	/* BlockStatus != SUCCESS */
+			printk(KERN_WARNING
+			       "%s - Error:\n  ErrorInfoSize = 0x%02x, "
+			       "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
+			       (cmd ==
+				I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" :
+			       "PARAMS_GET", res32[1] >> 24,
+			       (res32[1] >> 16) & 0xFF, res32[1] & 0xFFFF);
+
+			/*
+			 *      If this is the only request,than we return an error
+			 */
+			if ((res32[0] & 0x0000FFFF) == 1) {
+				return -((res32[1] >> 16) & 0xFF);	/* -BlockStatus */
+			}
+		}
+		len += restmp[0] & 0x0000FFFF;	/* Length of res BLOCK */
+		restmp += restmp[0] & 0x0000FFFF;	/* Skip to next BLOCK */
+	}
+	return (len << 2);	/* bytes used by result list */
+}
+
+/*
+ *	 Query one field group value or a whole scalar group.
+ */
+int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
+		       void *buf, int buflen)
+{
+	u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
+	u8 resblk[8 + buflen];	/* 8 bytes for header */
+	int size;
+
+	if (field == -1)	/* whole group */
+		opblk[4] = -1;
+
+	size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
+			      sizeof(opblk), resblk, sizeof(resblk));
+
+	memcpy(buf, resblk + 8, buflen);	/* cut off header */
+
+	if (size > buflen)
+		return buflen;
+
+	return size;
+}
+
+/*
+ *	Set a scalar group value or a whole group.
+ */
+int i2o_parm_field_set(struct i2o_device *i2o_dev, int group, int field,
+		       void *buf, int buflen)
+{
+	u16 *opblk;
+	u8 resblk[8 + buflen];	/* 8 bytes for header */
+	int size;
+
+	opblk = kmalloc(buflen + 64, GFP_KERNEL);
+	if (opblk == NULL) {
+		printk(KERN_ERR "i2o: no memory for operation buffer.\n");
+		return -ENOMEM;
+	}
+
+	opblk[0] = 1;		/* operation count */
+	opblk[1] = 0;		/* pad */
+	opblk[2] = I2O_PARAMS_FIELD_SET;
+	opblk[3] = group;
+
+	if (field == -1) {	/* whole group */
+		opblk[4] = -1;
+		memcpy(opblk + 5, buf, buflen);
+	} else {		/* single field */
+
+		opblk[4] = 1;
+		opblk[5] = field;
+		memcpy(opblk + 6, buf, buflen);
+	}
+
+	size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_SET, opblk,
+			      12 + buflen, resblk, sizeof(resblk));
+
+	kfree(opblk);
+	if (size > buflen)
+		return buflen;
+
+	return size;
+}
+
+/*
+ * 	if oper == I2O_PARAMS_TABLE_GET, get from all rows
+ * 		if fieldcount == -1 return all fields
+ *			ibuf and ibuflen are unused (use NULL, 0)
+ * 		else return specific fields
+ *  			ibuf contains fieldindexes
+ *
+ * 	if oper == I2O_PARAMS_LIST_GET, get from specific rows
+ * 		if fieldcount == -1 return all fields
+ *			ibuf contains rowcount, keyvalues
+ * 		else return specific fields
+ *			fieldcount is # of fieldindexes
+ *  			ibuf contains fieldindexes, rowcount, keyvalues
+ *
+ *	You could also use directly function i2o_issue_params().
+ */
+int i2o_parm_table_get(struct i2o_device *dev, int oper, int group,
+		       int fieldcount, void *ibuf, int ibuflen, void *resblk,
+		       int reslen)
+{
+	u16 *opblk;
+	int size;
+
+	size = 10 + ibuflen;
+	if (size % 4)
+		size += 4 - size % 4;
+
+	opblk = kmalloc(size, GFP_KERNEL);
+	if (opblk == NULL) {
+		printk(KERN_ERR "i2o: no memory for query buffer.\n");
+		return -ENOMEM;
+	}
+
+	opblk[0] = 1;		/* operation count */
+	opblk[1] = 0;		/* pad */
+	opblk[2] = oper;
+	opblk[3] = group;
+	opblk[4] = fieldcount;
+	memcpy(opblk + 5, ibuf, ibuflen);	/* other params */
+
+	size = i2o_parm_issue(dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
+			      size, resblk, reslen);
+
+	kfree(opblk);
+	if (size > reslen)
+		return reslen;
+
+	return size;
+}
+
+/**
+ *	i2o_device_init - Initialize I2O devices
+ *
+ *	Registers the I2O device class.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int i2o_device_init(void)
+{
+	int rc;
+
+	rc = class_register(&i2o_device_class);
+	if (rc)
+		return rc;
+
+	return class_interface_register(&i2o_device_class_interface);
+};
+
+/**
+ *	i2o_device_exit - I2O devices exit function
+ *
+ *	Unregisters the I2O device class.
+ */
+void i2o_device_exit(void)
+{
+	class_interface_register(&i2o_device_class_interface);
+	class_unregister(&i2o_device_class);
+};
+
+EXPORT_SYMBOL(i2o_device_claim);
+EXPORT_SYMBOL(i2o_device_claim_release);
+EXPORT_SYMBOL(i2o_parm_field_get);
+EXPORT_SYMBOL(i2o_parm_field_set);
+EXPORT_SYMBOL(i2o_parm_table_get);
+EXPORT_SYMBOL(i2o_parm_issue);
diff -Nru a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/message/i2o/driver.c	2004-08-19 09:24:16 -07:00
@@ -0,0 +1,367 @@
+/*
+ *	Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs
+ *
+ *	Copyright (C) 2004	Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *
+ *	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 of the License, or (at your
+ *	option) any later version.
+ *
+ *	Fixes/additions:
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *			initial version.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <linux/i2o.h>
+
+
+/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
+unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
+module_param_named(max_drivers, i2o_max_drivers, uint, 0);
+MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
+
+/* I2O drivers lock and array */
+static spinlock_t i2o_drivers_lock = SPIN_LOCK_UNLOCKED;
+static struct i2o_driver **i2o_drivers;
+
+/**
+ *	i2o_bus_match - Tell if a I2O device class id match the class ids of
+ *			the I2O driver (OSM)
+ *
+ *	@dev: device which should be verified
+ *	@drv: the driver to match against
+ *
+ *	Used by the bus to check if the driver wants to handle the device.
+ *
+ *	Returns 1 if the class ids of the driver match the class id of the
+ *	device, otherwise 0.
+ */
+static int i2o_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_driver *i2o_drv = to_i2o_driver(drv);
+	struct i2o_class_id *ids = i2o_drv->classes;
+
+	if (ids)
+		while (ids->class_id != I2O_CLASS_END) {
+			if (ids->class_id == i2o_dev->lct_data.class_id)
+				return 1;
+			ids++;
+		}
+	return 0;
+};
+
+/* I2O bus type */
+struct bus_type i2o_bus_type = {
+	.name = "i2o",
+	.match = i2o_bus_match,
+};
+
+/**
+ *	i2o_driver_register - Register a I2O driver (OSM) in the I2O core
+ *	@drv: I2O driver which should be registered
+ *
+ *	Registers the OSM drv in the I2O core and creates an event queues if
+ *	necessary.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int i2o_driver_register(struct i2o_driver *drv)
+{
+	struct i2o_controller *c;
+	int i;
+	int rc = 0;
+	unsigned long flags;
+
+	pr_debug("Register driver %s\n", drv->name);
+
+	if (drv->event) {
+		drv->event_queue = create_workqueue(drv->name);
+		if (!drv->event_queue) {
+			printk(KERN_ERR "i2o: Could not initialize event queue "
+			       "for driver %s\n", drv->name);
+			return -EFAULT;
+		}
+		pr_debug("Event queue initialized for driver %s\n", drv->name);
+	} else
+		drv->event_queue = NULL;
+
+	drv->driver.name = drv->name;
+	drv->driver.bus = &i2o_bus_type;
+
+	spin_lock_irqsave(&i2o_drivers_lock, flags);
+
+	for (i = 0; i2o_drivers[i]; i++)
+		if (i >= i2o_max_drivers) {
+			printk(KERN_ERR "i2o: too many drivers registered, "
+			       "increase max_drivers\n");
+			spin_unlock_irqrestore(&i2o_drivers_lock, flags);
+			return -EFAULT;
+		}
+
+	drv->context = i;
+	i2o_drivers[i] = drv;
+
+	spin_unlock_irqrestore(&i2o_drivers_lock, flags);
+
+	pr_debug("driver %s gets context id %d\n", drv->name, drv->context);
+
+	list_for_each_entry(c, &i2o_controllers, list) {
+		struct i2o_device *i2o_dev;
+
+		i2o_driver_notify_controller_add(drv, c);
+		list_for_each_entry(i2o_dev, &c->devices, list)
+			i2o_driver_notify_device_add(drv, i2o_dev);
+	}
+
+
+	rc = driver_register(&drv->driver);
+	if (rc)
+		destroy_workqueue(drv->event_queue);
+
+	return rc;
+};
+
+/**
+ *	i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core
+ *	@drv: I2O driver which should be unregistered
+ *
+ *	Unregisters the OSM drv from the I2O core and cleanup event queues if
+ *	necessary.
+ */
+void i2o_driver_unregister(struct i2o_driver *drv)
+{
+	struct i2o_controller *c;
+	unsigned long flags;
+
+	pr_debug("unregister driver %s\n", drv->name);
+
+	driver_unregister(&drv->driver);
+
+	list_for_each_entry(c, &i2o_controllers, list) {
+		struct i2o_device *i2o_dev;
+
+		list_for_each_entry(i2o_dev, &c->devices, list)
+			i2o_driver_notify_device_remove(drv, i2o_dev);
+
+		i2o_driver_notify_controller_remove(drv, c);
+	}
+
+	spin_lock_irqsave(&i2o_drivers_lock, flags);
+	i2o_drivers[drv->context] = NULL;
+	spin_unlock_irqrestore(&i2o_drivers_lock, flags);
+
+	if (drv->event_queue) {
+		destroy_workqueue(drv->event_queue);
+		drv->event_queue = NULL;
+		pr_debug("event queue removed for %s\n", drv->name);
+	}
+};
+
+/**
+ *	i2o_driver_dispatch - dispatch an I2O reply message
+ *	@c: I2O controller of the message
+ *	@m: I2O message number
+ *	@msg: I2O message to be delivered
+ *
+ *	The reply is delivered to the driver from which the original message
+ *	was. This function is only called from interrupt context.
+ *
+ *	Returns 0 on success and the message should not be flushed. Returns > 0
+ *	on success and if the message should be flushed afterwords. Returns
+ *	negative error code on failure (the message will be flushed too).
+ */
+int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
+			struct i2o_message *msg)
+{
+	struct i2o_driver *drv;
+	u32 context = readl(&msg->u.s.icntxt);
+
+	if (likely(context < i2o_max_drivers)) {
+		spin_lock(&i2o_drivers_lock);
+		drv = i2o_drivers[context];
+		spin_unlock(&i2o_drivers_lock);
+
+		if (unlikely(!drv)) {
+			printk(KERN_WARNING "i2o: Spurious reply to unknown "
+			       "driver %d\n", context);
+			return -EIO;
+		}
+
+		if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
+			struct i2o_device *dev, *tmp;
+			struct i2o_event *evt;
+			u16 size;
+			u16 tid;
+
+			tid = readl(&msg->u.head[1]) & 0x1fff;
+
+			pr_debug("%s: event received from device %d\n", c->name,
+				 tid);
+
+			/* cut of header from message size (in 32-bit words) */
+			size = (readl(&msg->u.head[0]) >> 16) - 5;
+
+			evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
+			if (!evt)
+				return -ENOMEM;
+			memset(evt, 0, size * 4 + sizeof(*evt));
+
+			evt->size = size;
+			memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt,
+				      (size + 2) * 4);
+
+			list_for_each_entry_safe(dev, tmp, &c->devices, list)
+			    if (dev->lct_data.tid == tid) {
+				evt->i2o_dev = dev;
+				break;
+			}
+
+			INIT_WORK(&evt->work, (void (*)(void *))drv->event,
+				  evt);
+			queue_work(drv->event_queue, &evt->work);
+			return 1;
+		}
+
+		if (likely(drv->reply))
+			return drv->reply(c, m, msg);
+		else
+			pr_debug("%s: Reply to driver %s, but no reply function"
+				 " defined!\n", c->name, drv->name);
+		return -EIO;
+	} else
+		printk(KERN_WARNING "i2o: Spurious reply to unknown driver "
+		       "%d\n", readl(&msg->u.s.icntxt));
+	return -EIO;
+}
+
+/**
+ *	i2o_driver_notify_controller_add_all - Send notify of added controller
+ *					       to all I2O drivers
+ *
+ *	Send notifications to all registered drivers that a new controller was
+ *	added.
+ */
+void i2o_driver_notify_controller_add_all(struct i2o_controller *c) {
+	int i;
+	struct i2o_driver *drv;
+
+	for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
+		drv = i2o_drivers[i];
+
+		if(drv)
+			i2o_driver_notify_controller_add(drv, c);
+	}
+}
+
+/**
+ *	i2o_driver_notify_controller_remove_all - Send notify of removed
+ *						  controller to all I2O drivers
+ *
+ *	Send notifications to all registered drivers that a controller was
+ *	removed.
+ */
+void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) {
+	int i;
+	struct i2o_driver *drv;
+
+	for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
+		drv = i2o_drivers[i];
+
+		if(drv)
+			i2o_driver_notify_controller_remove(drv, c);
+	}
+}
+
+/**
+ *	i2o_driver_notify_device_add_all - Send notify of added device to all
+ *					   I2O drivers
+ *
+ *	Send notifications to all registered drivers that a device was added.
+ */
+void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) {
+	int i;
+	struct i2o_driver *drv;
+
+	for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
+		drv = i2o_drivers[i];
+
+		if(drv)
+			i2o_driver_notify_device_add(drv, i2o_dev);
+	}
+}
+
+/**
+ *	i2o_driver_notify_device_remove_all - Send notify of removed device to
+ *					      all I2O drivers
+ *
+ *	Send notifications to all registered drivers that a device was removed.
+ */
+void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) {
+	int i;
+	struct i2o_driver *drv;
+
+	for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
+		drv = i2o_drivers[i];
+
+		if(drv)
+			i2o_driver_notify_device_remove(drv, i2o_dev);
+	}
+}
+
+/**
+ *	i2o_driver_init - initialize I2O drivers (OSMs)
+ *
+ *	Registers the I2O bus and allocate memory for the array of OSMs.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int __init i2o_driver_init(void)
+{
+	int rc = 0;
+
+	if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
+	    ((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
+	     (2 * i2o_max_drivers - 1))) {
+		printk(KERN_WARNING "i2o: max_drivers set to %d, but must be "
+		       ">=2 and <= 64 and a power of 2\n", i2o_max_drivers);
+		i2o_max_drivers = I2O_MAX_DRIVERS;
+	}
+	printk(KERN_INFO "i2o: max_drivers=%d\n", i2o_max_drivers);
+
+	i2o_drivers =
+	    kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
+	if (!i2o_drivers)
+		return -ENOMEM;
+
+	memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers));
+
+	rc = bus_register(&i2o_bus_type);
+
+	if (rc < 0)
+		kfree(i2o_drivers);
+
+	return rc;
+};
+
+/**
+ *	i2o_driver_exit - clean up I2O drivers (OSMs)
+ *
+ *	Unregisters the I2O bus and free driver array.
+ */
+void __exit i2o_driver_exit(void)
+{
+	bus_unregister(&i2o_bus_type);
+	kfree(i2o_drivers);
+};
+
+EXPORT_SYMBOL(i2o_driver_register);
+EXPORT_SYMBOL(i2o_driver_unregister);
+EXPORT_SYMBOL(i2o_driver_notify_controller_add_all);
+EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all);
+EXPORT_SYMBOL(i2o_driver_notify_device_add_all);
+EXPORT_SYMBOL(i2o_driver_notify_device_remove_all);
diff -Nru a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/message/i2o/exec-osm.c	2004-08-24 11:29:31 -07:00
@@ -0,0 +1,505 @@
+/*
+ *	Executive OSM
+ *
+ * 	Copyright (C) 1999-2002	Red Hat Software
+ *
+ *	Written by Alan Cox, Building Number Three Ltd
+ *
+ *	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 of the License, or (at your
+ *	option) any later version.
+ *
+ *	A lot of the I2O message side code from this is taken from the Red
+ *	Creek RCPCI45 adapter driver by Red Creek Communications
+ *
+ *	Fixes/additions:
+ *		Philipp Rumpf
+ *		Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ *		Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ *		Deepak Saxena <deepak@plexity.net>
+ *		Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
+ *		Alan Cox <alan@redhat.com>:
+ *			Ported to Linux 2.5.
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *			Minor fixes for 2.6.
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *			Support for sysfs included.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+
+struct i2o_driver i2o_exec_driver;
+
+/* Module internal functions from other sources */
+extern int i2o_device_parse_lct(struct i2o_controller *);
+
+/* global wait list for POST WAIT */
+static LIST_HEAD(i2o_exec_wait_list);
+
+/* Wait struct needed for POST WAIT */
+struct i2o_exec_wait {
+	wait_queue_head_t *wq;	/* Pointer to Wait queue */
+	struct i2o_dma dma;	/* DMA buffers to free on failure */
+	u32 tcntxt;		/* transaction context from reply */
+	int complete;		/* 1 if reply received otherwise 0 */
+	u32 m;			/* message id */
+	struct i2o_message *msg;	/* pointer to the reply message */
+	struct list_head list;	/* node in global wait list */
+};
+
+/* Exec OSM class handling definition */
+static struct i2o_class_id i2o_exec_class_id[] = {
+	{I2O_CLASS_EXECUTIVE},
+	{I2O_CLASS_END}
+};
+
+/**
+ *	i2o_exec_wait_alloc - Allocate a i2o_exec_wait struct an initialize it
+ *
+ *	Allocate the i2o_exec_wait struct and initialize the wait.
+ *
+ *	Returns i2o_exec_wait pointer on success or negative error code on
+ *	failure.
+ */
+static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
+{
+	struct i2o_exec_wait *wait;
+
+	wait = kmalloc(sizeof(*wait), GFP_KERNEL);
+	if (!wait)
+		return ERR_PTR(-ENOMEM);
+
+	memset(wait, 0, sizeof(*wait));
+
+	INIT_LIST_HEAD(&wait->list);
+
+	return wait;
+};
+
+/**
+ *	i2o_exec_wait_free - Free a i2o_exec_wait struct
+ *	@i2o_exec_wait: I2O wait data which should be cleaned up
+ */
+static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
+{
+	kfree(wait);
+};
+
+/**
+ * 	i2o_msg_post_wait_mem - Post and wait a message with DMA buffers
+ *	@c: controller
+ *	@m: message to post
+ *	@timeout: time in seconds to wait
+ *	@dma: i2o_dma struct of the DMA buffer to free on failure
+ *
+ * 	This API allows an OSM to post a message and then be told whether or
+ *	not the system received a successful reply. If the message times out
+ *	then the value '-ETIMEDOUT' is returned. This is a special case. In
+ *	this situation the message may (should) complete at an indefinite time
+ *	in the future. When it completes it will use the memory buffer
+ *	attached to the request. If -ETIMEDOUT is returned then the memory
+ *	buffer must not be freed. Instead the event completion will free them
+ *	for you. In all other cases the buffer are your problem.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
+			  timeout, struct i2o_dma *dma)
+{
+	DECLARE_WAIT_QUEUE_HEAD(wq);
+	DEFINE_WAIT(wait);
+	struct i2o_exec_wait *iwait;
+	static u32 tcntxt = 0x80000000;
+	struct i2o_message *msg = c->in_queue.virt + m;
+	int rc = 0;
+
+	iwait = i2o_exec_wait_alloc();
+	if (!iwait)
+		return -ENOMEM;
+
+	if (tcntxt == 0xffffffff)
+		tcntxt = 0x80000000;
+
+	if (dma)
+		iwait->dma = *dma;
+
+	/*
+	 * Fill in the message initiator context and transaction context.
+	 * We will only use transaction contexts >= 0x80000000 for POST WAIT,
+	 * so we could find a POST WAIT reply easier in the reply handler.
+	 */
+	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+	iwait->tcntxt = tcntxt++;
+	writel(iwait->tcntxt, &msg->u.s.tcntxt);
+
+	/*
+	 * Post the message to the controller. At some point later it will
+	 * return. If we time out before it returns then complete will be zero.
+	 */
+	i2o_msg_post(c, m);
+
+	if (!iwait->complete) {
+		iwait->wq = &wq;
+		/*
+		 * we add elements add the head, because if a entry in the list
+		 * will never be removed, we have to iterate over it every time
+		 */
+		list_add(&iwait->list, &i2o_exec_wait_list);
+
+		prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
+
+		if (!iwait->complete)
+			schedule_timeout(timeout * HZ);
+
+		finish_wait(&wq, &wait);
+
+		iwait->wq = NULL;
+	}
+
+	barrier();
+
+	if (iwait->complete) {
+		if (readl(&iwait->msg->body[0]) >> 24)
+			rc = readl(&iwait->msg->body[0]) & 0xff;
+		i2o_flush_reply(c, iwait->m);
+		i2o_exec_wait_free(iwait);
+	} else {
+		/*
+		 * We cannot remove it now. This is important. When it does
+		 * terminate (which it must do if the controller has not
+		 * died...) then it will otherwise scribble on stuff.
+		 *
+		 * FIXME: try abort message
+		 */
+		if (dma)
+			dma->virt = NULL;
+
+		rc = -ETIMEDOUT;
+	}
+
+	return rc;
+};
+
+/**
+ *	i2o_msg_post_wait_complete - Reply to a i2o_msg_post request from IOP
+ *	@c: I2O controller which answers
+ *	@m: message id
+ *	@msg: pointer to the I2O reply message
+ *
+ *	This function is called in interrupt context only. If the reply reached
+ *	before the timeout, the i2o_exec_wait struct is filled with the message
+ *	and the task will be waked up. The task is now responsible for returning
+ *	the message m back to the controller! If the message reaches us after
+ *	the timeout clean up the i2o_exec_wait struct (including allocated
+ *	DMA buffer).
+ *
+ *	Return 0 on success and if the message m should not be given back to the
+ *	I2O controller, or >0 on success and if the message should be given back
+ *	afterwords. Returns negative error code on failure. In this case the
+ *	message must also be given back to the controller.
+ */
+static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
+				      struct i2o_message *msg)
+{
+	struct i2o_exec_wait *wait, *tmp;
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+	int rc = 1;
+	u32 context;
+
+	context = readl(&msg->u.s.tcntxt);
+
+	/*
+	 * We need to search through the i2o_exec_wait_list to see if the given
+	 * message is still outstanding. If not, it means that the IOP took
+	 * longer to respond to the message than we had allowed and timer has
+	 * already expired. Not much we can do about that except log it for
+	 * debug purposes, increase timeout, and recompile.
+	 */
+	spin_lock(&lock);
+	list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
+		if (wait->tcntxt == context) {
+			list_del(&wait->list);
+
+			wait->m = m;
+			wait->msg = msg;
+			wait->complete = 1;
+
+			barrier();
+
+			if (wait->wq) {
+				wake_up_interruptible(wait->wq);
+				rc = 0;
+			} else {
+				struct device *dev;
+
+				dev = &c->pdev->dev;
+
+				pr_debug("timedout reply received!\n");
+				i2o_dma_free(dev, &wait->dma);
+				i2o_exec_wait_free(wait);
+				rc = -1;
+			}
+
+			spin_unlock(&lock);
+
+			return rc;
+		}
+	}
+
+	spin_unlock(&lock);
+
+	pr_debug("i2o: Bogus reply in POST WAIT (tr-context: %08x)!\n",
+		 context);
+
+	return -1;
+};
+
+/**
+ *	i2o_exec_probe - Called if a new I2O device (executive class) appears
+ *	@dev: I2O device which should be probed
+ *
+ *	Registers event notification for every event from Executive device. The
+ *	return is always 0, because we want all devices of class Executive.
+ *
+ *	Returns 0 on success.
+ */
+static int i2o_exec_probe(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+
+	i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
+
+	i2o_dev->iop->exec = i2o_dev;
+
+	return 0;
+};
+
+/**
+ *	i2o_exec_remove - Called on I2O device removal
+ *	@dev: I2O device which was removed
+ *
+ *	Unregisters event notification from Executive I2O device.
+ *
+ *	Returns 0 on success.
+ */
+static int i2o_exec_remove(struct device *dev)
+{
+	i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
+
+	return 0;
+};
+
+/**
+ *	i2o_exec_lct_modified - Called on LCT NOTIFY reply
+ *	@c: I2O controller on which the LCT has modified
+ *
+ *	This function handles asynchronus LCT NOTIFY replies. It parses the
+ *	new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
+ *	again.
+ */
+static void i2o_exec_lct_modified(struct i2o_controller *c)
+{
+	if (i2o_device_parse_lct(c) == -EAGAIN)
+		i2o_exec_lct_notify(c, 0);
+};
+
+/**
+ *	i2o_exec_reply -  I2O Executive reply handler
+ *	@c: I2O controller from which the reply comes
+ *	@m: message id
+ *	@msg: pointer to the I2O reply message
+ *
+ *	This function is always called from interrupt context. If a POST WAIT
+ *	reply was received, pass it to the complete function. If a LCT NOTIFY
+ *	reply was received, a new event is created to handle the update.
+ *
+ *	Returns 0 on success and if the reply should not be flushed or > 0
+ *	on success and if the reply should be flushed. Returns negative error
+ *	code on failure and if the reply should be flushed.
+ */
+static int i2o_exec_reply(struct i2o_controller *c, u32 m,
+			  struct i2o_message *msg)
+{
+	if (readl(&msg->u.head[0]) & MSG_FAIL) {	// Fail bit is set
+		struct i2o_message *pmsg;	/* preserved message */
+		u32 pm;
+
+		pm = readl(&msg->body[3]);
+
+		pmsg = c->in_queue.virt + pm;
+
+		i2o_report_status(KERN_INFO, "i2o_core", msg);
+
+		/* Release the preserved msg by resubmitting it as a NOP */
+		i2o_msg_nop(c, pm);
+
+		/* If reply to i2o_post_wait failed, return causes a timeout */
+		return -1;
+	}
+
+	if (readl(&msg->u.s.tcntxt) & 0x80000000)
+		return i2o_msg_post_wait_complete(c, m, msg);
+
+	if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
+		struct work_struct *work;
+
+		pr_debug("%s: LCT notify received\n", c->name);
+
+		work = kmalloc(sizeof(*work), GFP_ATOMIC);
+		if (!work)
+			return -ENOMEM;
+
+		INIT_WORK(work, (void (*)(void *))i2o_exec_lct_modified, c);
+		queue_work(i2o_exec_driver.event_queue, work);
+		return 1;
+	}
+
+	/*
+	 * If this happens, we want to dump the message to the syslog so
+	 * it can be sent back to the card manufacturer by the end user
+	 * to aid in debugging.
+	 *
+	 */
+	printk(KERN_WARNING "%s: Unsolicited message reply sent to core!"
+	       "Message dumped to syslog\n", c->name);
+	i2o_dump_message(msg);
+
+	return -EFAULT;
+}
+
+/**
+ *	i2o_exec_event - Event handling function
+ *	@evt: Event which occurs
+ *
+ *	Handles events send by the Executive device. At the moment does not do
+ *	anything useful.
+ */
+static void i2o_exec_event(struct i2o_event *evt)
+{
+	printk(KERN_INFO "Event received from device: %d\n",
+	       evt->i2o_dev->lct_data.tid);
+	kfree(evt);
+};
+
+/**
+ *	i2o_exec_lct_get - Get the IOP's Logical Configuration Table
+ *	@c: I2O controller from which the LCT should be fetched
+ *
+ *	Send a LCT NOTIFY request to the controller, and wait
+ *	I2O_TIMEOUT_LCT_GET seconds until arrival of response. If the LCT is
+ *	to large, retry it.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int i2o_exec_lct_get(struct i2o_controller *c)
+{
+	struct i2o_message *msg;
+	u32 m;
+	int i = 0;
+	int rc = -EAGAIN;
+
+	for (i = 1; i <= I2O_LCT_GET_TRIES; i++) {
+		m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+		if (m == I2O_QUEUE_EMPTY)
+			return -ETIMEDOUT;
+
+		writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
+		writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
+		       &msg->u.head[1]);
+		writel(0xffffffff, &msg->body[0]);
+		writel(0x00000000, &msg->body[1]);
+		writel(0xd0000000 | c->dlct.len, &msg->body[2]);
+		writel(c->dlct.phys, &msg->body[3]);
+
+		rc = i2o_msg_post_wait(c, m, I2O_TIMEOUT_LCT_GET);
+		if (rc < 0)
+			break;
+
+		rc = i2o_device_parse_lct(c);
+		if (rc != -EAGAIN)
+			break;
+	}
+
+	return rc;
+}
+
+/**
+ *	i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request
+ *	@c: I2O controller to which the request should be send
+ *	@change_ind: change indicator
+ *
+ *	This function sends a LCT NOTIFY request to the I2O controller with
+ *	the change indicator change_ind. If the change_ind == 0 the controller
+ *	replies immediately after the request. If change_ind > 0 the reply is
+ *	send after change indicator of the LCT is > change_ind.
+ */
+int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
+{
+	i2o_status_block *sb = c->status_block.virt;
+	struct device *dev;
+	struct i2o_message *msg;
+	u32 m;
+
+	dev = &c->pdev->dev;
+
+	if (i2o_dma_realloc(dev, &c->dlct, sb->expected_lct_size, GFP_KERNEL))
+		return -ENOMEM;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
+	writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+	writel(0, &msg->u.s.tcntxt);	/* FIXME */
+	writel(0xffffffff, &msg->body[0]);
+	writel(change_ind, &msg->body[1]);
+	writel(0xd0000000 | c->dlct.len, &msg->body[2]);
+	writel(c->dlct.phys, &msg->body[3]);
+
+	i2o_msg_post(c, m);
+
+	return 0;
+};
+
+/* Exec OSM driver struct */
+struct i2o_driver i2o_exec_driver = {
+	.name = "exec-osm",
+	.reply = i2o_exec_reply,
+	.event = i2o_exec_event,
+	.classes = i2o_exec_class_id,
+	.driver = {
+		   .probe = i2o_exec_probe,
+		   .remove = i2o_exec_remove,
+		   },
+};
+
+/**
+ *	i2o_exec_init - Registers the Exec OSM
+ *
+ *	Registers the Exec OSM in the I2O core.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int __init i2o_exec_init(void)
+{
+	return i2o_driver_register(&i2o_exec_driver);
+};
+
+/**
+ *	i2o_exec_exit - Removes the Exec OSM
+ *
+ *	Unregisters the Exec OSM from the I2O core.
+ */
+void __exit i2o_exec_exit(void)
+{
+	i2o_driver_unregister(&i2o_exec_driver);
+};
+
+EXPORT_SYMBOL(i2o_msg_post_wait_mem);
+EXPORT_SYMBOL(i2o_exec_lct_get);
+EXPORT_SYMBOL(i2o_exec_lct_notify);
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	2004-06-22 07:51:25 -07:00
+++ b/drivers/message/i2o/i2o_block.c	2004-08-24 11:29:24 -07:00
@@ -1,463 +1,426 @@
 /*
- * I2O Random Block Storage Class OSM
+ *	Block OSM
  *
- * (C) Copyright 1999-2002 Red Hat
- *	
- * Written by Alan Cox, Building Number Three Ltd
- *
- * 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 of the License, 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.
- *
- * For the purpose of avoiding doubt the preferred form of the work
- * for making modifications shall be a standards compliant form such
- * gzipped tar and not one requiring a proprietary or patent encumbered
- * tool to unpack.
- *
- * This is a beta test release. Most of the good code was taken
- * from the nbd driver by Pavel Machek, who in turn took some of it
- * from loop.c. Isn't free software great for reusability 8)
- *
- * Fixes/additions:
- *	Steve Ralston:	
- *		Multiple device handling error fixes,
- *		Added a queue depth.
- *	Alan Cox:	
- *		FC920 has an rmw bug. Dont or in the end marker.
- *		Removed queue walk, fixed for 64bitness.
- *		Rewrote much of the code over time
- *		Added indirect block lists
- *		Handle 64K limits on many controllers
- *		Don't use indirects on the Promise (breaks)
- *		Heavily chop down the queue depths
- *	Deepak Saxena:
- *		Independent queues per IOP
- *		Support for dynamic device creation/deletion
- *		Code cleanup	
- *    		Support for larger I/Os through merge* functions 
- *       	(taken from DAC960 driver)
- *	Boji T Kannanthanam:
- *		Set the I2O Block devices to be detected in increasing 
- *		order of TIDs during boot.
- *		Search and set the I2O block device that we boot off from  as
- *		the first device to be claimed (as /dev/i2o/hda)
- *		Properly attach/detach I2O gendisk structure from the system
- *		gendisk list. The I2O block devices now appear in 
- * 		/proc/partitions.
- *	Markus Lidel <Markus.Lidel@shadowconnect.com>:
- *		Minor bugfixes for 2.6.
+ * 	Copyright (C) 1999-2002	Red Hat Software
  *
- * To do:
- *	Serial number scanning to find duplicates for FC multipathing
+ *	Written by Alan Cox, Building Number Three Ltd
+ *
+ *	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 of the License, 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.
+ *
+ *	For the purpose of avoiding doubt the preferred form of the work
+ *	for making modifications shall be a standards compliant form such
+ *	gzipped tar and not one requiring a proprietary or patent encumbered
+ *	tool to unpack.
+ *
+ *	Fixes/additions:
+ *		Steve Ralston:
+ *			Multiple device handling error fixes,
+ *			Added a queue depth.
+ *		Alan Cox:
+ *			FC920 has an rmw bug. Dont or in the end marker.
+ *			Removed queue walk, fixed for 64bitness.
+ *			Rewrote much of the code over time
+ *			Added indirect block lists
+ *			Handle 64K limits on many controllers
+ *			Don't use indirects on the Promise (breaks)
+ *			Heavily chop down the queue depths
+ *		Deepak Saxena:
+ *			Independent queues per IOP
+ *			Support for dynamic device creation/deletion
+ *			Code cleanup
+ *	    		Support for larger I/Os through merge* functions
+ *			(taken from DAC960 driver)
+ *		Boji T Kannanthanam:
+ *			Set the I2O Block devices to be detected in increasing
+ *			order of TIDs during boot.
+ *			Search and set the I2O block device that we boot off
+ *			from as the first device to be claimed (as /dev/i2o/hda)
+ *			Properly attach/detach I2O gendisk structure from the
+ *			system gendisk list. The I2O block devices now appear in
+ *			/proc/partitions.
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *			Minor bugfixes for 2.6.
  */
 
-#include <linux/major.h>
-
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/file.h>
-#include <linux/ioctl.h>
 #include <linux/i2o.h>
+
+#include <linux/mempool.h>
+
+#include <linux/genhd.h>
 #include <linux/blkdev.h>
-#include <linux/blkpg.h>
-#include <linux/slab.h>
 #include <linux/hdreg.h>
-#include <linux/spinlock.h>
-#include <linux/bio.h>
 
-#include <linux/notifier.h>
-#include <linux/reboot.h>
+#include "i2o_block.h"
 
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-#include <linux/completion.h>
-#include <asm/io.h>
-#include <linux/smp_lock.h>
-#include <linux/wait.h>
-
-#define MAJOR_NR I2O_MAJOR
-
-#define MAX_I2OB	16
-
-#define MAX_I2OB_DEPTH	8
-#define MAX_I2OB_RETRIES 4
-
-//#define DRIVERDEBUG
-#ifdef DRIVERDEBUG
-#define DEBUG( s ) printk( s )
-#else
-#define DEBUG( s )
-#endif
+static struct i2o_driver i2o_block_driver;
 
-/*
- * Events that this OSM is interested in
- */
-#define I2OB_EVENT_MASK		(I2O_EVT_IND_BSA_VOLUME_LOAD |	\
-				 I2O_EVT_IND_BSA_VOLUME_UNLOAD | \
-				 I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ | \
-				 I2O_EVT_IND_BSA_CAPACITY_CHANGE | \
-				 I2O_EVT_IND_BSA_SCSI_SMART )
+/* global Block OSM request mempool */
+static struct i2o_block_mempool i2o_blk_req_pool;
 
+/* Block OSM class handling definition */
+static struct i2o_class_id i2o_block_class_id[] = {
+	{I2O_CLASS_RANDOM_BLOCK_STORAGE},
+	{I2O_CLASS_END}
+};
 
-/*
- *	Some of these can be made smaller later
+/**
+ *	i2o_block_device_free - free the memory of the I2O Block device
+ *	@dev: I2O Block device, which should be cleaned up
+ *
+ *	Frees the request queue, gendisk and the i2o_block_device structure.
  */
+static void i2o_block_device_free(struct i2o_block_device *dev)
+{
+	blk_cleanup_queue(dev->gd->queue);
 
-static int i2ob_context;
-static struct block_device_operations i2ob_fops;
+	put_disk(dev->gd);
 
-/*
- * I2O Block device descriptor 
+	kfree(dev);
+};
+
+/**
+ *	i2o_block_remove - remove the I2O Block device from the system again
+ *	@dev: I2O Block device which should be removed
+ *
+ *	Remove gendisk from system and free all allocated memory.
+ *
+ *	Always returns 0.
  */
-struct i2ob_device
+static int i2o_block_remove(struct device *dev)
 {
-	struct i2o_controller *controller;
-	struct i2o_device *i2odev;
-	int unit;
-	int tid;
-	int flags;
-	int refcnt;
-	struct request *head, *tail;
-	request_queue_t *req_queue;
-	int max_segments;
-	int max_direct;		/* Not yet used properly */
-	int done_flag;
-	int depth;
-	int rcache;
-	int wcache;
-	int power;
-	int index;
-	int media_change_flag;
-	u32 max_sectors;
-	struct gendisk *gd;
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev);
+
+	printk(KERN_INFO "block-osm: Device removed %s\n",
+	       i2o_blk_dev->gd->disk_name);
+
+	i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);
+
+	del_gendisk(i2o_blk_dev->gd);
+
+	dev_set_drvdata(dev, NULL);
+
+	i2o_device_claim_release(i2o_dev);
+
+	i2o_block_device_free(i2o_blk_dev);
+
+	return 0;
 };
 
-/*
- *	FIXME:
- *	We should cache align these to avoid ping-ponging lines on SMP
- *	boxes under heavy I/O load...
+/**
+ *	i2o_block_device flush - Flush all dirty data of I2O device dev
+ *	@dev: I2O device which should be flushed
+ *
+ *	Flushes all dirty data on device dev.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-
-struct i2ob_request
+static int i2o_block_device_flush(struct i2o_device *dev)
 {
-	struct i2ob_request *next;
-	struct request *req;
-	int num;
-	int sg_dma_direction;
-	int sg_nents;
-	struct scatterlist sg_table[16];
+	struct i2o_message *msg;
+	u32 m;
+
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(60 << 16, &msg->body[0]);
+	pr_debug("Flushing...\n");
+
+	return i2o_msg_post_wait(dev->iop, m, 60);
 };
 
-/*
- * Per IOP request queue information
+/**
+ *	i2o_block_device_mount - Mount (load) the media of device dev
+ *	@dev: I2O device which should receive the mount request
+ *	@media_id: Media Identifier
+ *
+ *	Load a media into drive. Identifier should be set to -1, because the
+ *	spec does not support any other value.
  *
- * We have a separate request_queue_t per IOP so that a heavilly
- * loaded I2O block device on an IOP does not starve block devices
- * across all I2O controllers.
- * 
- */
-struct i2ob_iop_queue
-{
-	unsigned int queue_depth;
-	struct i2ob_request request_queue[MAX_I2OB_DEPTH];
-	struct i2ob_request *i2ob_qhead;
-	request_queue_t *req_queue;
-	spinlock_t lock;
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
+{
+	struct i2o_message *msg;
+	u32 m;
+
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(-1, &msg->body[0]);
+	writel(0, &msg->body[1]);
+	pr_debug("Mounting...\n");
+
+	return i2o_msg_post_wait(dev->iop, m, 2);
 };
-static struct i2ob_iop_queue *i2ob_queues[MAX_I2O_CONTROLLERS];
 
-/*
- *	Each I2O disk is one of these.
+/**
+ *	i2o_block_device_lock - Locks the media of device dev
+ *	@dev: I2O device which should receive the lock request
+ *	@media_id: Media Identifier
+ *
+ *	Lock media of device dev to prevent removal. The media identifier
+ *	should be set to -1, because the spec does not support any other value.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
+static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
+{
+	struct i2o_message *msg;
+	u32 m;
 
-static struct i2ob_device i2ob_dev[MAX_I2OB];
-static int i2ob_dev_count = 0;
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(-1, &msg->body[0]);
+	pr_debug("Locking...\n");
 
-/*
- * Mutex and spin lock for event handling synchronization
- * evt_msg contains the last event.
+	return i2o_msg_post_wait(dev->iop, m, 2);
+};
+
+/**
+ *	i2o_block_device_unlock - Unlocks the media of device dev
+ *	@dev: I2O device which should receive the unlocked request
+ *	@media_id: Media Identifier
+ *
+ *	Unlocks the media in device dev. The media identifier should be set to
+ *	-1, because the spec does not support any other value.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-static DECLARE_MUTEX_LOCKED(i2ob_evt_sem);
-static DECLARE_COMPLETION(i2ob_thread_dead);
-static spinlock_t i2ob_evt_lock = SPIN_LOCK_UNLOCKED;
-static u32 evt_msg[MSG_FRAME_SIZE];
-
-static void i2o_block_reply(struct i2o_handler *, struct i2o_controller *,
-	 struct i2o_message *);
-static void i2ob_new_device(struct i2o_controller *, struct i2o_device *);
-static void i2ob_del_device(struct i2o_controller *, struct i2o_device *);
-static void i2ob_reboot_event(void);
-static int i2ob_install_device(struct i2o_controller *, struct i2o_device *, int);
-static void i2ob_end_request(struct request *);
-static void i2ob_request(request_queue_t *);
-static int i2ob_init_iop(unsigned int);
-static int i2ob_query_device(struct i2ob_device *, int, int, void*, int);
-static int i2ob_evt(void *);
-
-static int evt_pid = 0;
-static int evt_running = 0;
-static int scan_unit = 0;
+static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id)
+{
+	struct i2o_message *msg;
+	u32 m;
 
-/*
- * I2O OSM registration structure...keeps getting bigger and bigger :)
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(media_id, &msg->body[0]);
+	pr_debug("Unlocking...\n");
+
+	return i2o_msg_post_wait(dev->iop, m, 2);
+};
+
+/**
+ *	i2o_block_device_power - Power management for device dev
+ *	@dev: I2O device which should receive the power management request
+ *	@operation: Operation which should be send
+ *
+ *	Send a power management request to the device dev.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-static struct i2o_handler i2o_block_handler =
+static int i2o_block_device_power(struct i2o_block_device *dev, u8 op)
 {
-	i2o_block_reply,
-	i2ob_new_device,
-	i2ob_del_device,
-	i2ob_reboot_event,
-	"I2O Block OSM",
-	0,
-	I2O_CLASS_RANDOM_BLOCK_STORAGE
+	struct i2o_device *i2o_dev = dev->i2o_dev;
+	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_message *msg;
+	u32 m;
+	int rc;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data.
+	       tid, &msg->u.head[1]);
+	writel(op << 24, &msg->body[0]);
+	pr_debug("Power...\n");
+
+	rc = i2o_msg_post_wait(c, m, 60);
+	if (!rc)
+		dev->power = op;
+
+	return rc;
 };
 
 /**
- *	i2ob_get	-	Get an I2O message
- *	@dev:  I2O block device
+ *	i2o_block_request_alloc - Allocate an I2O block request struct
+ *
+ *	Allocates an I2O block request struct and initialize the list.
  *
- *	Get a message from the FIFO used for this block device. The message is returned
- *	or the I2O 'no message' value of 0xFFFFFFFF if nothing is available.
+ *	Returns a i2o_block_request pointer on success or negative error code
+ *	on failure.
  */
+static inline struct i2o_block_request *i2o_block_request_alloc(void)
+{
+	struct i2o_block_request *ireq;
+
+	ireq = mempool_alloc(i2o_blk_req_pool.pool, GFP_ATOMIC);
+	if (!ireq)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&ireq->queue);
+
+	return ireq;
+};
 
-static u32 i2ob_get(struct i2ob_device *dev)
+/**
+ *	i2o_block_request_free - Frees a I2O block request
+ *	@ireq: I2O block request which should be freed
+ *
+ *	Fres the allocated memory (give it back to the request mempool).
+ */
+static inline void i2o_block_request_free(struct i2o_block_request *ireq)
 {
-	struct i2o_controller *c=dev->controller;
-   	return I2O_POST_READ32(c);
-}
+	mempool_free(ireq, i2o_blk_req_pool.pool);
+};
 
-static int i2ob_build_sglist(struct i2ob_device *dev,  struct i2ob_request *ireq)
+/**
+ *	i2o_block_sglist_alloc - Allocate the SG list and map it
+ *	@ireq: I2O block request
+ *
+ *	Builds the SG list and map it into to be accessable by the controller.
+ *
+ *	Returns the number of elements in the SG list or 0 on failure.
+ */
+static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq)
 {
-	struct scatterlist *sg = ireq->sg_table;
+	struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
 	int nents;
 
-	nents = blk_rq_map_sg(dev->req_queue, ireq->req, ireq->sg_table);
-		
+	nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table);
+
 	if (rq_data_dir(ireq->req) == READ)
 		ireq->sg_dma_direction = PCI_DMA_FROMDEVICE;
 	else
 		ireq->sg_dma_direction = PCI_DMA_TODEVICE;
 
-	ireq->sg_nents = pci_map_sg(dev->controller->pdev, sg, nents, ireq->sg_dma_direction);
+	ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents,
+				    ireq->sg_dma_direction);
+
 	return ireq->sg_nents;
-}
+};
 
-void i2ob_free_sglist(struct i2ob_device *dev, struct i2ob_request *ireq)
-{
-	struct pci_dev *pdev = dev->controller->pdev;
-	struct scatterlist *sg = ireq->sg_table;
-	int nents = ireq->sg_nents;
-	pci_unmap_sg(pdev, sg, nents, ireq->sg_dma_direction);
-}
- 
 /**
- *	i2ob_send		-	Turn a request into a message and send it
- *	@m: Message offset
- *	@dev: I2O device
- *	@ireq: Request structure
- *	@unit: Device identity
- *
- *	Generate an I2O BSAREAD request. This interface function is called for devices that
- *	appear to explode when they are fed indirect chain pointers (notably right now this
- *	appears to afflict Promise hardwre, so be careful what you feed the hardware
- *
- *	No cleanup is done by this interface. It is done on the interrupt side when the
- *	reply arrives
- */
- 
-static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, int unit)
-{
-	struct i2o_controller *c = dev->controller;
-	int tid = dev->tid;
-	void *msg;
-	void *mptr;
-	u64 offset;
-	struct request *req = ireq->req;
-	int count = req->nr_sectors<<9;
-	struct scatterlist *sg;
-	int sgnum;
-	int i;
+ *	i2o_block_sglist_free - Frees the SG list
+ *	@ireq: I2O block request from which the SG should be freed
+ *
+ *	Frees the SG list from the I2O block request.
+ */
+static inline void i2o_block_sglist_free(struct i2o_block_request *ireq)
+{
+	struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
 
-	// printk(KERN_INFO "i2ob_send called\n");
-	/* Map the message to a virtual address */
-	msg = c->msg_virt + m;
-	
-	sgnum = i2ob_build_sglist(dev, ireq);
-	
-	/* FIXME: if we have no resources how should we get out of this */
-	if(sgnum == 0)
-		BUG();
-	
-	/*
-	 * Build the message based on the request.
-	 */
-	i2o_raw_writel(i2ob_context|(unit<<8), msg+8);
-	i2o_raw_writel(ireq->num, msg+12);
-	i2o_raw_writel(req->nr_sectors << 9, msg+20);
+	dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents,
+		     ireq->sg_dma_direction);
+};
 
-	/* 
-	 * Mask out partitions from now on
-	 */
-		
-	/* This can be optimised later - just want to be sure its right for
-	   starters */
-	offset = ((u64)req->sector) << 9;
-	i2o_raw_writel( offset & 0xFFFFFFFF, msg+24);
-	i2o_raw_writel(offset>>32, msg+28);
-	mptr=msg+32;
-	
-	sg = ireq->sg_table;
-	if(rq_data_dir(req) == READ)
-	{
-		DEBUG("READ\n");
-		i2o_raw_writel(I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid, msg+4);
-		for(i = sgnum; i > 0; i--)
-		{
-			if(i != 1)
-				i2o_raw_writel(0x10000000|sg_dma_len(sg), mptr);
-			else
-				i2o_raw_writel(0xD0000000|sg_dma_len(sg), mptr);
-			i2o_raw_writel(sg_dma_address(sg), mptr+4);
-			mptr += 8;	
-			count -= sg_dma_len(sg);
-			sg++;
-		}
-		switch(dev->rcache)
-		{
-			case CACHE_NULL:
-				i2o_raw_writel(0, msg+16);break;
-			case CACHE_PREFETCH:
-				i2o_raw_writel(0x201F0008, msg+16);break;
-			case CACHE_SMARTFETCH:
-				if(req->nr_sectors > 16)
-					i2o_raw_writel(0x201F0008, msg+16);
-				else
-					i2o_raw_writel(0x001F0000, msg+16);
-				break;
-		}				
-				
-//		printk("Reading %d entries %d bytes.\n",
-//			mptr-msg-8, req->nr_sectors<<9);
-	}
-	else if(rq_data_dir(req) == WRITE)
-	{
-		DEBUG("WRITE\n");
-		i2o_raw_writel(I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid, msg+4);
-		for(i = sgnum; i > 0; i--)
-		{
-			if(i != 1)
-				i2o_raw_writel(0x14000000|sg_dma_len(sg), mptr);
-			else
-				i2o_raw_writel(0xD4000000|sg_dma_len(sg), mptr);
-			i2o_raw_writel(sg_dma_address(sg), mptr+4);
-			mptr += 8;	
-			count -= sg_dma_len(sg);
-			sg++;
-		}
+/**
+ *	i2o_block_prep_req_fn - Allocates I2O block device specific struct
+ *	@q: request queue for the request
+ *	@req: the request to prepare
+ *
+ *	Allocate the necessary i2o_block_request struct and connect it to
+ *	the request. This is needed that we not loose the SG list later on.
+ *
+ *	Returns BLKPREP_OK on success or BLKPREP_DEFER on failure.
+ */
+static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
+{
+	struct i2o_block_device *i2o_blk_dev = q->queuedata;
+	struct i2o_block_request *ireq;
 
-		switch(dev->wcache)
-		{
-			case CACHE_NULL:
-				i2o_raw_writel(0, msg+16);break;
-			case CACHE_WRITETHROUGH:
-				i2o_raw_writel(0x001F0008, msg+16);break;
-			case CACHE_WRITEBACK:
-				i2o_raw_writel(0x001F0010, msg+16);break;
-			case CACHE_SMARTBACK:
-				if(req->nr_sectors > 16)
-					i2o_raw_writel(0x001F0004, msg+16);
-				else
-					i2o_raw_writel(0x001F0010, msg+16);
-				break;
-			case CACHE_SMARTTHROUGH:
-				if(req->nr_sectors > 16)
-					i2o_raw_writel(0x001F0004, msg+16);
-				else
-					i2o_raw_writel(0x001F0010, msg+16);
+	/* request is already processed by us, so return */
+	if (req->flags & REQ_SPECIAL) {
+		pr_debug("REQ_SPECIAL already set!\n");
+		req->flags |= REQ_DONTPREP;
+		return BLKPREP_OK;
+	}
+
+	/* connect the i2o_block_request to the request */
+	if (!req->special) {
+		ireq = i2o_block_request_alloc();
+		if (unlikely(IS_ERR(ireq))) {
+			pr_debug("unable to allocate i2o_block_request!\n");
+			return BLKPREP_DEFER;
 		}
-				
-//		printk("Writing %d entries %d bytes.\n",
-//			mptr-msg-8, req->nr_sectors<<9);
-	}
-	i2o_raw_writel(I2O_MESSAGE_SIZE(mptr-msg)>>2 | SGL_OFFSET_8, msg);
-	
-	if(count != 0)
-	{
-		printk(KERN_ERR "Request count botched by %d.\n", count);
-	}
 
-	i2o_post_message(c,m);
-	i2ob_queues[c->unit]->queue_depth ++;
+		ireq->i2o_blk_dev = i2o_blk_dev;
+		req->special = ireq;
+		ireq->req = req;
+	} else
+		ireq = req->special;
 
-	return 0;
-}
+	/* do not come back here */
+	req->flags |= REQ_DONTPREP | REQ_SPECIAL;
 
-/*
- *	Remove a request from the _locked_ request list. We update both the
- *	list chain and if this is the last item the tail pointer. Caller
- *	must hold the lock.
- */
- 
-static inline void i2ob_unhook_request(struct i2ob_request *ireq, 
-	unsigned int iop)
-{
-	ireq->next = i2ob_queues[iop]->i2ob_qhead;
-	i2ob_queues[iop]->i2ob_qhead = ireq;
-}
+	return BLKPREP_OK;
+};
 
-/*
- *	Request completion handler
+/**
+ *	i2o_block_delayed_request_fn - delayed request queue function
+ *	delayed_request: the delayed request with the queue to start
+ *
+ *	If the request queue is stopped for a disk, and there is no open
+ *	request, a new event is created, which calls this function to start
+ *	the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never
+ *	be started again.
  */
- 
-static inline void i2ob_end_request(struct request *req)
+static void i2o_block_delayed_request_fn(void *delayed_request)
 {
-	/* FIXME  - pci unmap the request */
-
-	/*
-	 * Loop until all of the buffers that are linked
-	 * to this request have been marked updated and
-	 * unlocked.
-	 */
-
-	while (end_that_request_first( req, !req->errors, req->hard_cur_sectors ));
+	struct i2o_block_delayed_request *dreq = delayed_request;
+	struct request_queue *q = dreq->queue;
+	unsigned long flags;
 
-	/*
-	 * It is now ok to complete the request.
-	 */
-	end_that_request_last( req );
-	DEBUG("IO COMPLETED\n");
-}
+	spin_lock_irqsave(q->queue_lock, flags);
+	blk_start_queue(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+	kfree(dreq);
+};
 
-/*
- *	OSM reply handler. This gets all the message replies
+/**
+ *	i2o_block_reply - Block OSM reply handler.
+ *	@c: I2O controller from which the message arrives
+ *	@m: message id of reply
+ *	qmsg: the actuall I2O message reply
+ *
+ *	This function gets all the message replies.
+ *
  */
-
-static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
+static int i2o_block_reply(struct i2o_controller *c, u32 m,
+			   struct i2o_message *msg)
 {
-	unsigned long flags;
-	struct i2ob_request *ireq = NULL;
+	struct i2o_block_request *ireq;
+	struct request *req;
+	struct i2o_block_device *dev;
+	struct request_queue *q;
 	u8 st;
-	u32 *m = (u32 *)msg;
-	u8 unit = m[2]>>8;
-	struct i2ob_device *dev = &i2ob_dev[unit];
+	unsigned long flags;
 
-	/*
-	 * FAILed message
-	 */
-	if(m[0] & (1<<13))
-	{
-		DEBUG("FAIL");
+	/* FAILed message */
+	if (unlikely(readl(&msg->u.head[0]) & (1 << 13))) {
+		struct i2o_message *pmsg;
+		u32 pm;
+
+		printk(KERN_WARNING "FAIL");
 		/*
 		 * FAILed message from controller
 		 * We increment the error count and abort it
@@ -468,65 +431,85 @@
 		 * better be on the safe side since no one really follows
 		 * the spec to the book :)
 		 */
-		ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
-		ireq->req->errors++;
+		pm = readl(&msg->body[3]);
+		pmsg = c->in_queue.virt + pm;
+
+		req = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
+		if (unlikely(!req)) {
+			printk(KERN_ERR "block-osm: NULL reply received!\n");
+			return -1;
+		}
+
+		ireq = req->special;
+		dev = ireq->i2o_blk_dev;
+		q = dev->gd->queue;
+
+		req->errors++;
+
+		spin_lock_irqsave(q->queue_lock, flags);
+
+		while (end_that_request_chunk(req, !req->errors,
+					      readl(&pmsg->body[1]))) ;
+		end_that_request_last(req);
+
+		dev->open_queue_depth--;
+		list_del(&ireq->queue);
+		blk_start_queue(q);
+
+		spin_unlock_irqrestore(q->queue_lock, flags);
 
-		spin_lock_irqsave(dev->req_queue->queue_lock, flags);
-		i2ob_unhook_request(ireq, c->unit);
-		i2ob_end_request(ireq->req);
-		spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
-	
 		/* Now flush the message by making it a NOP */
-		m[0]&=0x00FFFFFF;
-		m[0]|=(I2O_CMD_UTIL_NOP)<<24;
-		i2o_post_message(c, (unsigned long) m - (unsigned long) c->msg_virt);
+		i2o_msg_nop(c, pm);
 
-		return;
+		return -1;
 	}
 
-	if(msg->function == I2O_CMD_UTIL_EVT_REGISTER)
-	{
-		spin_lock(&i2ob_evt_lock);
-		memcpy(evt_msg, msg, (m[0]>>16)<<2);
-		spin_unlock(&i2ob_evt_lock);
-		up(&i2ob_evt_sem);
-		return;
+	req = i2o_cntxt_list_get(c, readl(&msg->u.s.tcntxt));
+	if (unlikely(!req)) {
+		printk(KERN_ERR "block-osm: NULL reply received!\n");
+		return -1;
 	}
 
-	if(!dev->i2odev)
-	{
+	ireq = req->special;
+	dev = ireq->i2o_blk_dev;
+	q = dev->gd->queue;
+
+	if (unlikely(!dev->i2o_dev)) {
 		/*
 		 * This is HACK, but Intel Integrated RAID allows user
-		 * to delete a volume that is claimed, locked, and in use 
+		 * to delete a volume that is claimed, locked, and in use
 		 * by the OS. We have to check for a reply from a
-		 * non-existent device and flag it as an error or the system 
+		 * non-existent device and flag it as an error or the system
 		 * goes kaput...
 		 */
-		ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
-		ireq->req->errors++;
-		printk(KERN_WARNING "I2O Block: Data transfer to deleted device!\n");
-		spin_lock_irqsave(dev->req_queue->queue_lock, flags);
-		i2ob_unhook_request(ireq, c->unit);
-		i2ob_end_request(ireq->req);
-		spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
-		return;
-	}	
+		req->errors++;
+		printk(KERN_WARNING
+		       "I2O Block: Data transfer to deleted device!\n");
+		spin_lock_irqsave(q->queue_lock, flags);
+		while (end_that_request_chunk
+		       (req, !req->errors, readl(&msg->body[1]))) ;
+		end_that_request_last(req);
+
+		dev->open_queue_depth--;
+		list_del(&ireq->queue);
+		blk_start_queue(q);
+
+		spin_unlock_irqrestore(q->queue_lock, flags);
+		return -1;
+	}
 
 	/*
-	 *	Lets see what is cooking. We stuffed the
-	 *	request in the context.
+	 *      Lets see what is cooking. We stuffed the
+	 *      request in the context.
 	 */
-		 
-	ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
-	st=m[4]>>24;
 
-	if(st!=0)
-	{
+	st = readl(&msg->body[0]) >> 24;
+
+	if (st != 0) {
 		int err;
-		char *bsa_errors[] = 
-		{ 
-			"Success", 
-			"Media Error", 
+		char *bsa_errors[] = {
+			"Success",
+			"Media Error",
 			"Failure communicating to device",
 			"Device Failure",
 			"Device is not ready",
@@ -540,61 +523,62 @@
 			"Device has reset",
 			"Volume has changed, waiting for acknowledgement"
 		};
-				
-		err = m[4]&0xFFFF;
-		
+
+		err = readl(&msg->body[0]) & 0xffff;
+
 		/*
-		 *	Device not ready means two things. One is that the
-		 *	the thing went offline (but not a removal media)
+		 *      Device not ready means two things. One is that the
+		 *      the thing went offline (but not a removal media)
 		 *
-		 *	The second is that you have a SuperTrak 100 and the
-		 *	firmware got constipated. Unlike standard i2o card
-		 *	setups the supertrak returns an error rather than
-		 *	blocking for the timeout in these cases. 
+		 *      The second is that you have a SuperTrak 100 and the
+		 *      firmware got constipated. Unlike standard i2o card
+		 *      setups the supertrak returns an error rather than
+		 *      blocking for the timeout in these cases.
 		 *
-		 *	Don't stick a supertrak100 into cache aggressive modes
+		 *      Don't stick a supertrak100 into cache aggressive modes
 		 */
-		 
-		
-		printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, 
-			bsa_errors[m[4]&0XFFFF]);
-		if(m[4]&0x00FF0000)
-			printk(" - DDM attempted %d retries", (m[4]>>16)&0x00FF );
+
+		printk(KERN_ERR "\n/dev/%s error: %s", dev->gd->disk_name,
+		       bsa_errors[readl(&msg->body[0]) & 0xffff]);
+		if (readl(&msg->body[0]) & 0x00ff0000)
+			printk(" - DDM attempted %d retries",
+			       (readl(&msg->body[0]) >> 16) & 0x00ff);
 		printk(".\n");
-		ireq->req->errors++;	
-	}
-	else
-		ireq->req->errors = 0;
+		req->errors++;
+	} else
+		req->errors = 0;
 
-	/*
-	 *	Dequeue the request. We use irqsave locks as one day we
-	 *	may be running polled controllers from a BH...
-	 */
-	
-	i2ob_free_sglist(dev, ireq);
-	spin_lock_irqsave(dev->req_queue->queue_lock, flags);
-	i2ob_unhook_request(ireq, c->unit);
-	i2ob_end_request(ireq->req);
-	i2ob_queues[c->unit]->queue_depth --;
-	
-	/*
-	 *	We may be able to do more I/O
-	 */
-	 
-	i2ob_request(dev->gd->queue);
-	spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
-}
+	if (!end_that_request_chunk(req, !req->errors, readl(&msg->body[1]))) {
+		add_disk_randomness(req->rq_disk);
+		spin_lock_irqsave(q->queue_lock, flags);
 
-/* 
- * Event handler.  Needs to be a separate thread b/c we may have
- * to do things like scan a partition table, or query parameters
- * which cannot be done from an interrupt or from a bottom half.
- */
-static int i2ob_evt(void *dummy)
+		end_that_request_last(req);
+
+		dev->open_queue_depth--;
+		list_del(&ireq->queue);
+		blk_start_queue(q);
+
+		spin_unlock_irqrestore(q->queue_lock, flags);
+
+		i2o_block_sglist_free(ireq);
+		i2o_block_request_free(ireq);
+	} else
+		printk(KERN_ERR "still remaining chunks\n");
+
+	return 1;
+};
+
+static void i2o_block_event(struct i2o_event *evt)
+{
+	printk(KERN_INFO "block-osm: event received\n");
+};
+
+#if 0
+static int i2o_block_event(void *dummy)
 {
 	unsigned int evt;
 	unsigned long flags;
-	struct i2ob_device *dev;
+	struct i2o_block_device *dev;
 	int unit;
 	//The only event that has data is the SCSI_SMART event.
 	struct i2o_reply {
@@ -604,24 +588,22 @@
 		u8 ASCQ;
 		u16 pad;
 		u8 data[16];
-		} *evt_local;
+	} *evt_local;
 
 	daemonize("i2oblock");
 	allow_signal(SIGKILL);
 
 	evt_running = 1;
 
-	while(1)
-	{
-		if(down_interruptible(&i2ob_evt_sem))
-		{
+	while (1) {
+		if (down_interruptible(&i2ob_evt_sem)) {
 			evt_running = 0;
 			printk("exiting...");
 			break;
 		}
 
 		/*
-		 * Keep another CPU/interrupt from overwriting the 
+		 * Keep another CPU/interrupt from overwriting the
 		 * message while we're reading it
 		 *
 		 * We stuffed the unit in the TxContext and grab the event mask
@@ -634,20 +616,19 @@
 		unit = le32_to_cpu(evt_local->header[3]);
 		evt = le32_to_cpu(evt_local->evt_indicator);
 
-		dev = &i2ob_dev[unit];
-		switch(evt)
-		{
+		dev = &i2o_blk_dev[unit];
+		switch (evt) {
 			/*
 			 * New volume loaded on same TID, so we just re-install.
 			 * The TID/controller don't change as it is the same
 			 * I2O device.  It's just new media that we have to
 			 * rescan.
 			 */
-			case I2O_EVT_IND_BSA_VOLUME_LOAD:
+		case I2O_EVT_IND_BSA_VOLUME_LOAD:
 			{
-				i2ob_install_device(dev->i2odev->controller,
-					dev->i2odev, unit);
-				add_disk(dev->gd);
+				i2ob_install_device(dev->i2o_device->iop,
+						    dev->i2o_device, unit);
+				add_disk(dev->gendisk);
 				break;
 			}
 
@@ -657,144 +638,108 @@
 			 * have media, so we don't want to clear the controller or
 			 * device pointer.
 			 */
-			case I2O_EVT_IND_BSA_VOLUME_UNLOAD:
+		case I2O_EVT_IND_BSA_VOLUME_UNLOAD:
 			{
-				struct gendisk *p = dev->gd;
-				blk_queue_max_sectors(dev->gd->queue, 0);
+				struct gendisk *p = dev->gendisk;
+				blk_queue_max_sectors(dev->gendisk->queue, 0);
 				del_gendisk(p);
 				put_disk(p);
-				dev->gd = NULL;
+				dev->gendisk = NULL;
 				dev->media_change_flag = 1;
 				break;
 			}
 
-			case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ:
-				printk(KERN_WARNING "%s: Attempt to eject locked media\n", 
-					dev->i2odev->dev_name);
-				break;
+		case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ:
+			printk(KERN_WARNING
+			       "%s: Attempt to eject locked media\n",
+			       dev->i2o_device->dev_name);
+			break;
 
 			/*
 			 * The capacity has changed and we are going to be
-			 * updating the max_sectors and other information 
+			 * updating the max_sectors and other information
 			 * about this disk.  We try a revalidate first. If
 			 * the block device is in use, we don't want to
 			 * do that as there may be I/Os bound for the disk
-			 * at the moment.  In that case we read the size 
+			 * at the moment.  In that case we read the size
 			 * from the device and update the information ourselves
 			 * and the user can later force a partition table
 			 * update through an ioctl.
 			 */
-			case I2O_EVT_IND_BSA_CAPACITY_CHANGE:
+		case I2O_EVT_IND_BSA_CAPACITY_CHANGE:
 			{
 				u64 size;
 
-	  			if(i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 )
-					i2ob_query_device(dev, 0x0000, 4, &size, 8);
-
-				spin_lock_irqsave(dev->req_queue->queue_lock, flags);
-				set_capacity(dev->gd, size>>9);
-				spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
+				if (i2ob_query_device(dev, 0x0004, 0, &size, 8)
+				    != 0)
+					i2ob_query_device(dev, 0x0000, 4, &size,
+							  8);
+
+				spin_lock_irqsave(dev->req_queue->queue_lock,
+						  flags);
+				set_capacity(dev->gendisk, size >> 9);
+				spin_unlock_irqrestore(dev->req_queue->
+						       queue_lock, flags);
 				break;
 			}
 
-			/* 
+			/*
 			 * We got a SCSI SMART event, we just log the relevant
 			 * information and let the user decide what they want
 			 * to do with the information.
 			 */
-			case I2O_EVT_IND_BSA_SCSI_SMART:
+		case I2O_EVT_IND_BSA_SCSI_SMART:
 			{
 				char buf[16];
-				printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",dev->i2odev->dev_name);
-				evt_local->data[16]='\0';
-				sprintf(buf,"%s",&evt_local->data[0]);
-				printk(KERN_INFO "      Disk Serial#:%s\n",buf);
-				printk(KERN_INFO "      ASC 0x%02x \n",evt_local->ASC);
-				printk(KERN_INFO "      ASCQ 0x%02x \n",evt_local->ASCQ);
+				printk(KERN_INFO
+				       "I2O Block: %s received a SCSI SMART Event\n",
+				       dev->i2o_device->dev_name);
+				evt_local->data[16] = '\0';
+				sprintf(buf, "%s", &evt_local->data[0]);
+				printk(KERN_INFO "      Disk Serial#:%s\n",
+				       buf);
+				printk(KERN_INFO "      ASC 0x%02x \n",
+				       evt_local->ASC);
+				printk(KERN_INFO "      ASCQ 0x%02x \n",
+				       evt_local->ASCQ);
 				break;
 			}
-		
+
 			/*
-			 *	Non event
+			 *      Non event
 			 */
-			 
-			case 0:
-				break;
-				
+
+		case 0:
+			break;
+
 			/*
 			 * An event we didn't ask for.  Call the card manufacturer
 			 * and tell them to fix their firmware :)
 			 */
-			 
-			case 0x20:
-				/*
-				 * If a promise card reports 0x20 event then the brown stuff
-				 * hit the fan big time. The card seems to recover but loses
-				 * the pending writes. Deeply ungood except for testing fsck
-				 */
-				if(dev->i2odev->controller->promise)
-					panic("I2O controller firmware failed. Reboot and force a filesystem check.\n");
-			default:
-				printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n"
-					KERN_INFO "   Blame the I2O card manufacturer 8)\n", 
-					dev->i2odev->dev_name, evt);
-				break;
-		}
-	};
-
-	complete_and_exit(&i2ob_thread_dead,0);
-	return 0;
-}
-
-/*
- *	The I2O block driver is listed as one of those that pulls the
- *	front entry off the queue before processing it. This is important
- *	to remember here. If we drop the io lock then CURRENT will change
- *	on us. We must unlink CURRENT in this routine before we return, if
- *	we use it.
- */
-
-static void i2ob_request(request_queue_t *q)
-{
-	struct request *req;
-	struct i2ob_request *ireq;
-	struct i2ob_device *dev;
-	u32 m;
-	
-	while ((req = elv_next_request(q)) != NULL) {
-		dev = req->rq_disk->private_data;
-
-		/* 
-		 *	Queue depths probably belong with some kind of 
-		 *	generic IOP commit control. Certainly it's not right 
-		 *	its global!  
-		 */
-		if(i2ob_queues[dev->unit]->queue_depth >= dev->depth)
-			break;
-		
-		/* Get a message */
-		m = i2ob_get(dev);
 
-		if(m==0xFFFFFFFF)
-		{
-			if(i2ob_queues[dev->unit]->queue_depth == 0)
-				printk(KERN_ERR "i2o_block: message queue and request queue empty!!\n");
+		case 0x20:
+			/*
+			 * If a promise card reports 0x20 event then the brown stuff
+			 * hit the fan big time. The card seems to recover but loses
+			 * the pending writes. Deeply ungood except for testing fsck
+			 */
+			if (dev->i2o_device->iop->promise)
+				panic
+				    ("I2O controller firmware failed. Reboot and force a filesystem check.\n");
+		default:
+			printk(KERN_INFO
+			       "%s: Received event 0x%X we didn't register for\n"
+			       KERN_INFO
+			       "   Blame the I2O card manufacturer 8)\n",
+			       dev->i2o_device->dev_name, evt);
 			break;
 		}
-		/*
-		 * Everything ok, so pull from kernel queue onto our queue
-		 */
-		req->errors = 0;
-		blkdev_dequeue_request(req);	
-		
-		ireq = i2ob_queues[dev->unit]->i2ob_qhead;
-		i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;
-		ireq->req = req;
+	};
 
-		i2ob_send(m, dev, ireq, dev->index);
-	}
+	complete_and_exit(&i2ob_thread_dead, 0);
+	return 0;
 }
-
+#endif
 
 /*
  *	SCSI-CAM for ioctl geometry mapping
@@ -803,8 +748,8 @@
  *
  * LBA -> CHS mapping table taken from:
  *
- * "Incorporating the I2O Architecture into BIOS for Intel Architecture 
- *  Platforms" 
+ * "Incorporating the I2O Architecture into BIOS for Intel Architecture
+ *  Platforms"
  *
  * This is an I2O document that is only available to I2O members,
  * not developers.
@@ -825,865 +770,647 @@
 #define	BLOCK_SIZE_42G		8806400
 #define	BLOCK_SIZE_84G		17612800
 
-static void i2o_block_biosparam(
-	unsigned long capacity,
-	unsigned short *cyls,
-	unsigned char *hds,
-	unsigned char *secs) 
-{ 
-	unsigned long heads, sectors, cylinders; 
+static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls,
+				unsigned char *hds, unsigned char *secs)
+{
+	unsigned long heads, sectors, cylinders;
 
-	sectors = 63L;      			/* Maximize sectors per track */ 
-	if(capacity <= BLOCK_SIZE_528M)
+	sectors = 63L;		/* Maximize sectors per track */
+	if (capacity <= BLOCK_SIZE_528M)
 		heads = 16;
-	else if(capacity <= BLOCK_SIZE_1G)
+	else if (capacity <= BLOCK_SIZE_1G)
 		heads = 32;
-	else if(capacity <= BLOCK_SIZE_21G)
+	else if (capacity <= BLOCK_SIZE_21G)
 		heads = 64;
-	else if(capacity <= BLOCK_SIZE_42G)
+	else if (capacity <= BLOCK_SIZE_42G)
 		heads = 128;
 	else
 		heads = 255;
 
 	cylinders = (unsigned long)capacity / (heads * sectors);
 
-	*cyls = (unsigned short) cylinders;	/* Stuff return values */ 
-	*secs = (unsigned char) sectors; 
-	*hds  = (unsigned char) heads; 
+	*cyls = (unsigned short)cylinders;	/* Stuff return values */
+	*secs = (unsigned char)sectors;
+	*hds = (unsigned char)heads;
 }
 
-/*
- *	Issue device specific ioctl calls.
+/**
+ *	i2o_block_open - Open the block device
+ *
+ *	Power up the device, mount and lock the media. This function is called,
+ *	if the block device is opened for access.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-
-static int i2ob_ioctl(struct inode *inode, struct file *file,
-		     unsigned int cmd, unsigned long arg)
+static int i2o_block_open(struct inode *inode, struct file *file)
 {
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct i2ob_device *dev = disk->private_data;
-	void __user *argp = (void __user *)arg;
+	struct i2o_block_device *dev = inode->i_bdev->bd_disk->private_data;
 
-	/* Anyone capable of this syscall can do *real bad* things */
+	if (!dev->i2o_dev)
+		return -ENODEV;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	switch (cmd) {
-		case HDIO_GETGEO:
-		{
-			struct hd_geometry g;
-			i2o_block_biosparam(get_capacity(disk), 
-					&g.cylinders, &g.heads, &g.sectors);
-			g.start = get_start_sect(inode->i_bdev);
-			return copy_to_user(argp, &g, sizeof(g))?-EFAULT:0;
-		}
-		
-		case BLKI2OGRSTRAT:
-			return put_user(dev->rcache, (int __user *)argp);
-		case BLKI2OGWSTRAT:
-			return put_user(dev->wcache, (int __user *)argp);
-		case BLKI2OSRSTRAT:
-			if(arg<0||arg>CACHE_SMARTFETCH)
-				return -EINVAL;
-			dev->rcache = arg;
-			break;
-		case BLKI2OSWSTRAT:
-			if(arg!=0 && (arg<CACHE_WRITETHROUGH || arg>CACHE_SMARTBACK))
-				return -EINVAL;
-			dev->wcache = arg;
-			break;
-	}
-	return -ENOTTY;
-}
+	if (dev->power > 0x1f)
+		i2o_block_device_power(dev, 0x02);
 
-/*
- *	Close the block device down
+	i2o_block_device_mount(dev->i2o_dev, -1);
+
+	i2o_block_device_lock(dev->i2o_dev, -1);
+
+	pr_debug("Ready.\n");
+
+	return 0;
+};
+
+/**
+ *	i2o_block_release - Release the I2O block device
+ *
+ *	Unlock and unmount the media, and power down the device. Gets called if
+ *	the block device is closed.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
- 
-static int i2ob_release(struct inode *inode, struct file *file)
+static int i2o_block_release(struct inode *inode, struct file *file)
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct i2ob_device *dev = disk->private_data;
+	struct i2o_block_device *dev = disk->private_data;
+	u8 operation;
 
 	/*
 	 * This is to deail with the case of an application
 	 * opening a device and then the device dissapears while
 	 * it's in use, and then the application tries to release
-	 * it.  ex: Unmounting a deleted RAID volume at reboot. 
+	 * it.  ex: Unmounting a deleted RAID volume at reboot.
 	 * If we send messages, it will just cause FAILs since
 	 * the TID no longer exists.
 	 */
-	if(!dev->i2odev)
+	if (!dev->i2o_dev)
 		return 0;
 
-	if (dev->refcnt <= 0)
-		printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt);
-	dev->refcnt--;
-	if(dev->refcnt==0)
-	{
-		/*
-		 *	Flush the onboard cache on unmount
-		 */
-		u32 msg[5];
-		int *query_done = &dev->done_flag;
-		msg[0] = (FIVE_WORD_MSG_SIZE|SGL_OFFSET_0);
-		msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid;
-		msg[2] = i2ob_context|0x40000000;
-		msg[3] = (u32)query_done;
-		msg[4] = 60<<16;
-		DEBUG("Flushing...");
-		i2o_post_wait(dev->controller, msg, 20, 60);
+	i2o_block_device_flush(dev->i2o_dev);
 
-		/*
-		 *	Unlock the media
-		 */
-		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-		msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid;
-		msg[2] = i2ob_context|0x40000000;
-		msg[3] = (u32)query_done;
-		msg[4] = -1;
-		DEBUG("Unlocking...");
-		i2o_post_wait(dev->controller, msg, 20, 2);
-		DEBUG("Unlocked.\n");
-
-		msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-		msg[1] = I2O_CMD_BLOCK_POWER<<24 | HOST_TID << 12 | dev->tid;
-		if(dev->flags & (1<<3|1<<4))	/* Removable */
-			msg[4] = 0x21 << 24;
-		else
-			msg[4] = 0x24 << 24;
+	i2o_block_device_unlock(dev->i2o_dev, -1);
 
-		if(i2o_post_wait(dev->controller, msg, 20, 60)==0)
-			dev->power = 0x24;
+	if (dev->flags & (1 << 3 | 1 << 4))	/* Removable */
+		operation = 0x21;
+	else
+		operation = 0x24;
 
-		/*
- 		 * Now unclaim the device.
-		 */
+	i2o_block_device_power(dev, operation);
 
-		if (i2o_release_device(dev->i2odev, &i2o_block_handler))
-			printk(KERN_ERR "i2ob_release: controller rejected unclaim.\n");
-		
-		DEBUG("Unclaim\n");
-	}
 	return 0;
 }
 
-/*
- *	Open the block device.
+/**
+ *	i2o_block_ioctl - Issue device specific ioctl calls.
+ *	@cmd: ioctl command
+ *	@arg: arg
+ *
+ *	Handles ioctl request for the block device.
+ *
+ *	Return 0 on success or negative error on failure.
  */
- 
-static int i2ob_open(struct inode *inode, struct file *file)
+static int i2o_block_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct i2ob_device *dev = disk->private_data;
+	struct i2o_block_device *dev = disk->private_data;
+	void __user *argp = (void __user *)arg;
 
-	if(!dev->i2odev)	
-		return -ENODEV;
-	
-	if(dev->refcnt++==0)
-	{ 
-		u32 msg[6];
-		
-		DEBUG("Claim ");
-		if(i2o_claim_device(dev->i2odev, &i2o_block_handler))
-		{
-			dev->refcnt--;
-			printk(KERN_INFO "I2O Block: Could not open device\n");
-			return -EBUSY;
-		}
-		DEBUG("Claimed ");
-		/*
-	 	 *	Power up if needed
-	 	 */
+	/* Anyone capable of this syscall can do *real bad* things */
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
 
-		if(dev->power > 0x1f)
+	switch (cmd) {
+	case HDIO_GETGEO:
 		{
-			msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-			msg[1] = I2O_CMD_BLOCK_POWER<<24 | HOST_TID << 12 | dev->tid;
-			msg[4] = 0x02 << 24;
-			if(i2o_post_wait(dev->controller, msg, 20, 60) == 0)
-				dev->power = 0x02;
+			struct hd_geometry g;
+			i2o_block_biosparam(get_capacity(disk),
+					    &g.cylinders, &g.heads, &g.sectors);
+			g.start = get_start_sect(inode->i_bdev);
+			return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0;
 		}
 
-		/*
-		 *	Mount the media if needed. Note that we don't use
-		 *	the lock bit. Since we have to issue a lock if it
-		 *	refuses a mount (quite possible) then we might as
-		 *	well just send two messages out.
-		 */
-		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;		
-		msg[1] = I2O_CMD_BLOCK_MMOUNT<<24|HOST_TID<<12|dev->tid;
-		msg[4] = -1;
-		msg[5] = 0;
-		DEBUG("Mount ");
-		i2o_post_wait(dev->controller, msg, 24, 2);
-
-		/*
-		 *	Lock the media
-		 */
-		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-		msg[1] = I2O_CMD_BLOCK_MLOCK<<24|HOST_TID<<12|dev->tid;
-		msg[4] = -1;
-		DEBUG("Lock ");
-		i2o_post_wait(dev->controller, msg, 20, 2);
-		DEBUG("Ready.\n");
-	}		
-	return 0;
-}
+	case BLKI2OGRSTRAT:
+		return put_user(dev->rcache, (int __user *)arg);
+	case BLKI2OGWSTRAT:
+		return put_user(dev->wcache, (int __user *)arg);
+	case BLKI2OSRSTRAT:
+		if (arg < 0 || arg > CACHE_SMARTFETCH)
+			return -EINVAL;
+		dev->rcache = arg;
+		break;
+	case BLKI2OSWSTRAT:
+		if (arg != 0
+		    && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK))
+			return -EINVAL;
+		dev->wcache = arg;
+		break;
+	}
+	return -ENOTTY;
+};
 
-/*
- *	Issue a device query
+/**
+ *	i2o_block_media_changed - Have we seen a media change?
+ *	@disk: gendisk which should be verified
+ *
+ *	Verifies if the media has changed.
+ *
+ *	Returns 1 if the media was changed or 0 otherwise.
  */
- 
-static int i2ob_query_device(struct i2ob_device *dev, int table, 
-	int field, void *buf, int buflen)
+static int i2o_block_media_changed(struct gendisk *disk)
 {
-	return i2o_query_scalar(dev->controller, dev->tid,
-		table, field, buf, buflen);
-}
+	struct i2o_block_device *p = disk->private_data;
 
+	if (p->media_change_flag) {
+		p->media_change_flag = 0;
+		return 1;
+	}
+	return 0;
+}
 
-/*
- *	Install the I2O block device we found.
+/**
+ *	i2o_block_transfer - Transfer a request to/from the I2O controller
+ *	@req: the request which should be transfered
+ *
+ *	This function converts the request into a I2O message. The necessary
+ *	DMA buffers are allocated and after everything is setup post the message
+ *	to the I2O controller. No cleanup is done by this function. It is done
+ *	on the interrupt side when the reply arrives.
+ *
+ *	Return 0 on success or negative error code on failure.
  */
- 
-static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, int unit)
+static int i2o_block_transfer(struct request *req)
 {
-	u64 size;
-	u32 blocksize;
-	u8 type;
-	u16 power;
-	u32 flags, status;
-	struct i2ob_device *dev=&i2ob_dev[unit];
-	struct gendisk *disk;
-	request_queue_t *q;
-	int segments;
+	struct i2o_block_device *dev = req->rq_disk->private_data;
+	struct i2o_controller *c = dev->i2o_dev->iop;
+	int tid = dev->i2o_dev->lct_data.tid;
+	struct i2o_message *msg;
+	void *mptr;
+	struct i2o_block_request *ireq = req->special;
+	struct scatterlist *sg;
+	int sgnum;
+	int i;
+	u32 m;
+	u32 tcntxt;
+	u32 sg_flags;
+	int rc;
 
+	m = i2o_msg_get(c, &msg);
+	if (m == I2O_QUEUE_EMPTY) {
+		rc = -EBUSY;
+		goto exit;
+	}
 
-	/*
-	 * For logging purposes...
-	 */
-	printk(KERN_INFO "i2ob: Installing tid %d device at unit %d\n", 
-			d->lct_data.tid, unit);	
+	tcntxt = i2o_cntxt_list_add(c, req);
+	if (!tcntxt) {
+		rc = -ENOMEM;
+		goto nop_msg;
+	}
 
-	/*
-	 * If this is the first I2O block device found on this IOP,
-	 * we need to initialize all the queue data structures
-	 * before any I/O can be performed. If it fails, this
-	 * device is useless.
-	 */
-	if(!i2ob_queues[c->unit]) {
-		if(i2ob_init_iop(c->unit))
-			return 1;
+	if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) {
+		rc = -ENOMEM;
+		goto context_remove;
 	}
 
-	q = i2ob_queues[c->unit]->req_queue;
+	/* Build the message based on the request. */
+	writel(i2o_block_driver.context, &msg->u.s.icntxt);
+	writel(tcntxt, &msg->u.s.tcntxt);
+	writel(req->nr_sectors << 9, &msg->body[1]);
 
-	/*
-	 * This will save one level of lookup/indirection in critical
-	 * code so that we can directly get the queue ptr from the
-	 * device instead of having to go the IOP data structure.
-	 */
-	dev->req_queue = q;
+	writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]);
+	writel(req->sector >> 23, &msg->body[3]);
 
-	/*
-	 * Allocate a gendisk structure and initialize it
-	 */
-	disk = alloc_disk(16);
-	if (!disk)
-		return 1;
+	mptr = &msg->body[4];
 
-	dev->gd = disk;
-	/* initialize gendik structure */
-	disk->major = MAJOR_NR;
-	disk->first_minor = unit<<4;
-	disk->queue = q;
-	disk->fops = &i2ob_fops;
-	sprintf(disk->disk_name, "i2o/hd%c", 'a' + unit);
-	disk->private_data = dev;
+	sg = ireq->sg_table;
 
-	/*
-	 *	Ask for the current media data. If that isn't supported
-	 *	then we ask for the device capacity data
-	 */
-	if(i2ob_query_device(dev, 0x0004, 1, &blocksize, 4) != 0
-	  || i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 )
-	{
-		i2ob_query_device(dev, 0x0000, 3, &blocksize, 4);
-		i2ob_query_device(dev, 0x0000, 4, &size, 8);
+	if (rq_data_dir(req) == READ) {
+		writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid,
+		       &msg->u.head[1]);
+		sg_flags = 0x10000000;
+		switch (dev->rcache) {
+		case CACHE_NULL:
+			writel(0, &msg->body[0]);
+			break;
+		case CACHE_PREFETCH:
+			writel(0x201F0008, &msg->body[0]);
+			break;
+		case CACHE_SMARTFETCH:
+			if (req->nr_sectors > 16)
+				writel(0x201F0008, &msg->body[0]);
+			else
+				writel(0x001F0000, &msg->body[0]);
+			break;
+		}
+	} else {
+		writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid,
+		       &msg->u.head[1]);
+		sg_flags = 0x14000000;
+		switch (dev->wcache) {
+		case CACHE_NULL:
+			writel(0, &msg->body[0]);
+			break;
+		case CACHE_WRITETHROUGH:
+			writel(0x001F0008, &msg->body[0]);
+			break;
+		case CACHE_WRITEBACK:
+			writel(0x001F0010, &msg->body[0]);
+			break;
+		case CACHE_SMARTBACK:
+			if (req->nr_sectors > 16)
+				writel(0x001F0004, &msg->body[0]);
+			else
+				writel(0x001F0010, &msg->body[0]);
+			break;
+		case CACHE_SMARTTHROUGH:
+			if (req->nr_sectors > 16)
+				writel(0x001F0004, &msg->body[0]);
+			else
+				writel(0x001F0010, &msg->body[0]);
+		}
 	}
-	
-	if(i2ob_query_device(dev, 0x0000, 2, &power, 2)!=0)
-		power = 0;
-	i2ob_query_device(dev, 0x0000, 5, &flags, 4);
-	i2ob_query_device(dev, 0x0000, 6, &status, 4);
-	set_capacity(disk, size>>9);
 
-	/*
-	 * Max number of Scatter-Gather Elements
-	 */	
+	for (i = sgnum; i > 0; i--) {
+		if (i == 1)
+			sg_flags |= 0x80000000;
+		writel(sg_flags | sg_dma_len(sg), mptr);
+		writel(sg_dma_address(sg), mptr + 4);
+		mptr += 8;
+		sg++;
+	}
+
+	writel(I2O_MESSAGE_SIZE
+	       (((unsigned long)mptr -
+		 (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8,
+	       &msg->u.head[0]);
 
-	dev->power = power;	/* Save power state in device proper */
-	dev->flags = flags;
+	i2o_msg_post(c, m);
 
-	segments = (d->controller->status_block->inbound_frame_size - 7) / 2;
+	list_add_tail(&ireq->queue, &dev->open_queue);
+	dev->open_queue_depth++;
 
-	if(segments > 16)
-		segments = 16;
-
-	dev->power = power;	/* Save power state */
-	dev->flags = flags;	/* Keep the type info */
-		
-	blk_queue_max_sectors(q, 96);	/* 256 might be nicer but many controllers
-						   explode on 65536 or higher */
-	blk_queue_max_phys_segments(q, segments);
-	blk_queue_max_hw_segments(q, segments);
-		
-	dev->rcache = CACHE_SMARTFETCH;
-	dev->wcache = CACHE_WRITETHROUGH;
-		
-	if(d->controller->battery == 0)
-		dev->wcache = CACHE_WRITETHROUGH;
-
-	if(d->controller->promise)
-		dev->wcache = CACHE_WRITETHROUGH;
-
-	if(d->controller->short_req)
-	{
-		blk_queue_max_sectors(q, 8);
-		blk_queue_max_phys_segments(q, 8);
-		blk_queue_max_hw_segments(q, 8);
-	}
-
-	strcpy(d->dev_name, disk->disk_name);
-	strcpy(disk->devfs_name, disk->disk_name);
-
-	printk(KERN_INFO "%s: Max segments %d, queue depth %d, byte limit %d.\n",
-		 d->dev_name, dev->max_segments, dev->depth, dev->max_sectors<<9);
-
-	i2ob_query_device(dev, 0x0000, 0, &type, 1);
-
-	printk(KERN_INFO "%s: ", d->dev_name);
-	switch(type)
-	{
-		case 0: printk("Disk Storage");break;
-		case 4: printk("WORM");break;
-		case 5: printk("CD-ROM");break;
-		case 7:	printk("Optical device");break;
-		default:
-			printk("Type %d", type);
-	}
-	if(status&(1<<10))
-		printk("(RAID)");
+	return 0;
 
-	if((flags^status)&(1<<4|1<<3))	/* Missing media or device */
-	{
-		printk(KERN_INFO " Not loaded.\n");
-		/* Device missing ? */
-		if((flags^status)&(1<<4))
-			return 1;
-	}
-	else
-	{
-		printk(": %dMB, %d byte sectors",
-			(int)(size>>20), blocksize);
-	}
-	if(status&(1<<0))
-	{
-		u32 cachesize;
-		i2ob_query_device(dev, 0x0003, 0, &cachesize, 4);
-		cachesize>>=10;
-		if(cachesize>4095)
-			printk(", %dMb cache", cachesize>>10);
-		else
-			printk(", %dKb cache", cachesize);
-	}
-	printk(".\n");
-	printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", 
-		d->dev_name, dev->max_sectors);
+      context_remove:
+	i2o_cntxt_list_remove(c, req);
 
-	/*
-	 * Register for the events we're interested in and that the
-	 * device actually supports.
-	 */
+      nop_msg:
+	i2o_msg_nop(c, m);
 
-	i2o_event_register(c, d->lct_data.tid, i2ob_context, unit, 
-		(I2OB_EVENT_MASK & d->lct_data.event_capabilities));
-	return 0;
-}
+      exit:
+	return rc;
+};
 
-/*
- * Initialize IOP specific queue structures.  This is called
- * once for each IOP that has a block device sitting behind it.
+/**
+ *	i2o_block_request_fn - request queue handling function
+ *	q: request queue from which the request could be fetched
+ *
+ *	Takes the next request from the queue, transfers it and if no error
+ *	occurs dequeue it from the queue. On arrival of the reply the message
+ *	will be processed further. If an error occurs requeue the request.
  */
-static int i2ob_init_iop(unsigned int unit)
+static void i2o_block_request_fn(struct request_queue *q)
 {
-	int i;
+	struct request *req;
 
-	i2ob_queues[unit] = (struct i2ob_iop_queue *) kmalloc(sizeof(struct i2ob_iop_queue), GFP_ATOMIC);
-	if(!i2ob_queues[unit])
-	{
-		printk(KERN_WARNING "Could not allocate request queue for I2O block device!\n");
-		return -1;
-	}
+	while (!blk_queue_plugged(q)) {
+		req = elv_next_request(q);
+		if (!req)
+			break;
 
-	for(i = 0; i< MAX_I2OB_DEPTH; i++)
-	{
-		i2ob_queues[unit]->request_queue[i].next =  &i2ob_queues[unit]->request_queue[i+1];
-		i2ob_queues[unit]->request_queue[i].num = i;
-	}
-	
-	/* Queue is MAX_I2OB + 1... */
-	i2ob_queues[unit]->request_queue[i].next = NULL;
-	i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0];
-	i2ob_queues[unit]->queue_depth = 0;
-
-	i2ob_queues[unit]->lock = SPIN_LOCK_UNLOCKED;
-	i2ob_queues[unit]->req_queue = blk_init_queue(i2ob_request, &i2ob_queues[unit]->lock);
-	if (!i2ob_queues[unit]->req_queue) {
-		kfree(i2ob_queues[unit]);
-		return -1;
-	}
+		if (blk_fs_request(req)) {
+			struct i2o_block_delayed_request *dreq;
+			struct i2o_block_request *ireq = req->special;
+			unsigned int queue_depth;
+
+			queue_depth = ireq->i2o_blk_dev->open_queue_depth;
+
+			if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS)
+				if (!i2o_block_transfer(req)) {
+					blkdev_dequeue_request(req);
+					continue;
+				}
 
-	i2ob_queues[unit]->req_queue->queuedata = &i2ob_queues[unit];
+			if (queue_depth)
+				break;
 
-	return 0;
-}
+			/* stop the queue and retry later */
+			dreq = kmalloc(sizeof(*dreq), GFP_ATOMIC);
+			if (!dreq)
+				continue;
 
-/*
- * Probe the I2O subsytem for block class devices
+			dreq->queue = q;
+			INIT_WORK(&dreq->work, i2o_block_delayed_request_fn,
+				  dreq);
+
+			printk(KERN_INFO "block-osm: transfer error\n");
+			if (!queue_delayed_work(i2o_block_driver.event_queue,
+						&dreq->work,
+						I2O_BLOCK_RETRY_TIME))
+				kfree(dreq);
+			else {
+				blk_stop_queue(q);
+				break;
+			}
+		} else
+			end_request(req, 0);
+	}
+};
+
+/* I2O Block device operations definition */
+static struct block_device_operations i2o_block_fops = {
+	.owner = THIS_MODULE,
+	.open = i2o_block_open,
+	.release = i2o_block_release,
+	.ioctl = i2o_block_ioctl,
+	.media_changed = i2o_block_media_changed
+};
+
+/**
+ *	i2o_block_device_alloc - Allocate memory for a I2O Block device
+ *
+ *	Allocate memory for the i2o_block_device struct, gendisk and request
+ *	queue and initialize them as far as no additional information is needed.
+ *
+ *	Returns a pointer to the allocated I2O Block device on succes or a
+ *	negative error code on failure.
  */
-static void i2ob_scan(int bios)
+static struct i2o_block_device *i2o_block_device_alloc(void)
 {
-	int i;
-	int warned = 0;
+	struct i2o_block_device *dev;
+	struct gendisk *gd;
+	struct request_queue *queue;
+	int rc;
 
-	struct i2o_device *d, *b=NULL;
-	struct i2o_controller *c;
-		
-	for(i=0; i< MAX_I2O_CONTROLLERS; i++)
-	{
-		c=i2o_find_controller(i);
-	
-		if(c==NULL)
-			continue;
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		printk(KERN_ERR "block-osm: Insufficient memory to allocate "
+		       "I2O Block disk.\n");
+		rc = -ENOMEM;
+		goto exit;
+	}
+	memset(dev, 0, sizeof(*dev));
 
-		/*
-		 *    The device list connected to the I2O Controller is doubly linked
-		 * Here we traverse the end of the list , and start claiming devices
-		 * from that end. This assures that within an I2O controller atleast
-		 * the newly created volumes get claimed after the older ones, thus
-		 * mapping to same major/minor (and hence device file name) after 
-		 * every reboot.
-		 * The exception being: 
-		 * 1. If there was a TID reuse.
-		 * 2. There was more than one I2O controller. 
-		 */
+	INIT_LIST_HEAD(&dev->open_queue);
+	spin_lock_init(&dev->lock);
+	dev->rcache = CACHE_PREFETCH;
+	dev->wcache = CACHE_WRITEBACK;
 
-		if(!bios)
-		{
-			for (d=c->devices;d!=NULL;d=d->next)
-			if(d->next == NULL)
-				b = d;
-		}
-		else
-			b = c->devices;
+	/* allocate a gendisk with 16 partitions */
+	gd = alloc_disk(16);
+	if (!gd) {
+		printk(KERN_ERR "block-osm: Insufficient memory to allocate "
+		       "gendisk.\n");
+		rc = -ENOMEM;
+		goto cleanup_dev;
+	}
 
-		while(b != NULL)
-		{
-			d=b;
-			if(bios)
-				b = b->next;
-			else
-				b = b->prev;
+	/* initialize the request queue */
+	queue = blk_init_queue(i2o_block_request_fn, &dev->lock);
+	if (!queue) {
+		printk(KERN_ERR "block-osm: Insufficient memory to allocate "
+		       "request queue.\n");
+		rc = -ENOMEM;
+		goto cleanup_queue;
+	}
 
-			if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
-				continue;
+	blk_queue_prep_rq(queue, i2o_block_prep_req_fn);
 
-			if(d->lct_data.user_tid != 0xFFF)
-				continue;
+	gd->major = I2O_MAJOR;
+	gd->queue = queue;
+	gd->fops = &i2o_block_fops;
+	gd->private_data = dev;
 
-			if(bios)
-			{
-				if(d->lct_data.bios_info != 0x80)
-					continue;
-				printk(KERN_INFO "Claiming as Boot device: Controller %d, TID %d\n", c->unit, d->lct_data.tid);
-			}
-			else
-			{
-				if(d->lct_data.bios_info == 0x80)
-					continue; /*Already claimed on pass 1 */
-			}
+	dev->gd = gd;
 
-			if(scan_unit<MAX_I2OB)
-				i2ob_new_device(c, d);
-			else
-			{
-				if(!warned++)
-					printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit);
-			}
-		}
-		i2o_unlock_controller(c);
-	}
-}
+	return dev;
 
-static void i2ob_probe(void)
-{
-	/*
-	 *      Some overhead/redundancy involved here, while trying to
-	 *      claim the first boot volume encountered as /dev/i2o/hda
-	 *      everytime. All the i2o_controllers are searched and the
-	 *      first i2o block device marked as bootable is claimed
-	 *      If an I2O block device was booted off , the bios sets
-	 *      its bios_info field to 0x80, this what we search for.
-	 *      Assuming that the bootable volume is /dev/i2o/hda
-	 *      everytime will prevent any kernel panic while mounting
-	 *      root partition
-	 */
+      cleanup_queue:
+	put_disk(gd);
 
-	printk(KERN_INFO "i2o_block: Checking for Boot device...\n");
-	i2ob_scan(1);
+      cleanup_dev:
+	kfree(dev);
 
-	/*
-	 *      Now the remainder.
-	 */
-	printk(KERN_INFO "i2o_block: Checking for I2O Block devices...\n");
-	i2ob_scan(0);
-}
+      exit:
+	return ERR_PTR(rc);
+};
 
+/**
+ *	i2o_block_probe - verify if dev is a I2O Block device and install it
+ *	@dev: device to verify if it is a I2O Block device
+ *
+ *	We only verify if the user_tid of the device is 0xfff and then install
+ *	the device. Otherwise it is used by some other device (e. g. RAID).
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_block_probe(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_block_device *i2o_blk_dev;
+	struct i2o_controller *c = i2o_dev->iop;
+	struct gendisk *gd;
+	struct request_queue *queue;
+	static int unit = 0;
+	int rc;
+	u64 size;
+	u32 blocksize;
+	u16 power;
+	u32 flags, status;
+	int segments;
 
-/*
- * New device notification handler.  Called whenever a new
- * I2O block storage device is added to the system.
- * 
- * Should we spin lock around this to keep multiple devs from 
- * getting updated at the same time? 
- * 
- */
-void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
-{
-	struct i2ob_device *dev;
-	int unit = 0;
-
-	printk(KERN_INFO "i2o_block: New device detected\n");
-	printk(KERN_INFO "   Controller %d Tid %d\n",c->unit, d->lct_data.tid);
-
-	/* Check for available space */
-	if(i2ob_dev_count>=MAX_I2OB)
-	{
-		printk(KERN_ERR "i2o_block: No more devices allowed!\n");
-		return;
-	}
-	for(unit = 0; unit < MAX_I2OB; unit ++)
-	{
-		if(!i2ob_dev[unit].i2odev)
-			break;
+	/* skip devices which are used by IOP */
+	if (i2o_dev->lct_data.user_tid != 0xfff) {
+		pr_debug("skipping used device %03x\n", i2o_dev->lct_data.tid);
+		return -ENODEV;
 	}
 
-	if(i2o_claim_device(d, &i2o_block_handler))
-	{
-		printk(KERN_INFO "i2o_block: Unable to claim device. Installation aborted\n");
-		return;
-	}
-
-	dev = &i2ob_dev[unit];
-	dev->i2odev = d; 
-	dev->controller = c;
-	dev->tid = d->lct_data.tid;
-	dev->unit = c->unit;
-
-	if(i2ob_install_device(c,d,unit)) {
-		i2o_release_device(d, &i2o_block_handler);
-		printk(KERN_ERR "i2o_block: Could not install new device\n");
-	}
-	else	
-	{
-		i2o_release_device(d, &i2o_block_handler);
-		add_disk(dev->gd);
-		i2ob_dev_count++;
-		i2o_device_notify_on(d, &i2o_block_handler);
+	printk(KERN_INFO "block-osm: New device detected (TID: %03x)\n",
+	       i2o_dev->lct_data.tid);
+
+	if (i2o_device_claim(i2o_dev)) {
+		printk(KERN_WARNING "block-osm: Unable to claim device. "
+		       "Installation aborted\n");
+		rc = -EFAULT;
+		goto exit;
 	}
 
-	return;
-}
+	i2o_blk_dev = i2o_block_device_alloc();
+	if (IS_ERR(i2o_blk_dev)) {
+		printk(KERN_ERR "block-osm: could not alloc a new I2O block"
+		       "device");
+		rc = PTR_ERR(i2o_blk_dev);
+		goto claim_release;
+	}
 
-/*
- * Deleted device notification handler.  Called when a device we
- * are talking to has been deleted by the user or some other
- * mysterious fource outside the kernel.
- */
-void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
-{	
-	int unit = 0;
-	unsigned long flags;
-	struct i2ob_device *dev;
+	i2o_blk_dev->i2o_dev = i2o_dev;
+	dev_set_drvdata(dev, i2o_blk_dev);
 
-	for(unit = 0; unit < MAX_I2OB; unit ++)
-	{
-		dev = &i2ob_dev[unit];
-		if(dev->i2odev == d)
-		{
-			printk(KERN_INFO "  /dev/%s: Controller %d Tid %d\n", 
-				d->dev_name, c->unit, d->lct_data.tid);
-			break;
-		}
-	}
+	/* setup gendisk */
+	gd = i2o_blk_dev->gd;
+	gd->first_minor = unit << 4;
+	sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit);
+	sprintf(gd->devfs_name, "i2o/hd%c", 'a' + unit);
+	gd->driverfs_dev = &i2o_dev->device;
+
+	/* setup request queue */
+	queue = gd->queue;
+	queue->queuedata = i2o_blk_dev;
+
+	blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS);
+	blk_queue_max_sectors(queue, I2O_MAX_SECTORS);
 
-	printk(KERN_INFO "I2O Block Device Deleted\n");
+	if (c->short_req)
+		segments = 8;
+	else {
+		i2o_status_block *sb;
 
-	if(unit >= MAX_I2OB)
-	{
-		printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");
-		return;
+		sb = c->status_block.virt;
+
+		segments = (sb->inbound_frame_size -
+			    sizeof(struct i2o_message) / 4 - 4) / 2;
 	}
 
-	spin_lock_irqsave(dev->req_queue->queue_lock, flags);
+	blk_queue_max_hw_segments(queue, segments);
+
+	pr_debug("max sectors:   %d\n", I2O_MAX_SECTORS);
+	pr_debug("phys segments: %d\n", I2O_MAX_SEGMENTS);
+	pr_debug("hw segments:   %d\n", segments);
 
 	/*
-	 * Need to do this...we somtimes get two events from the IRTOS
-	 * in a row and that causes lots of problems.
+	 *      Ask for the current media data. If that isn't supported
+	 *      then we ask for the device capacity data
 	 */
-	i2o_device_notify_off(d, &i2o_block_handler);
+	if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0
+	    || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) {
+		i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4);
+		i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8);
+	}
+	pr_debug("blocksize:     %d\n", blocksize);
 
-	/* 
-	 * This will force errors when i2ob_get_queue() is called
-	 * by the kenrel.
-	 */
-	if(dev->gd) {
-		struct gendisk *gd = dev->gd;
-		gd->queue = NULL;
-		del_gendisk(gd);
-		put_disk(gd);
-		dev->gd = NULL;
-	}
-	spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
-	dev->req_queue = NULL;
-	dev->i2odev = NULL;
-	dev->refcnt = 0;
-	dev->tid = 0;
-
-	/* 
-	 * Do we need this?
-	 * The media didn't really change...the device is just gone
-	 */
-	dev->media_change_flag = 1;
+	if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
+		power = 0;
+	i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
+	i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
 
-	i2ob_dev_count--;	
-}
+	set_capacity(gd, size >> 9);
 
-/*
- *	Have we seen a media change ?
- */
-static int i2ob_media_change(struct gendisk *disk)
-{
-	struct i2ob_device *p = disk->private_data;
-	if(p->media_change_flag)
-	{
-		p->media_change_flag=0;
-		return 1;
-	}
-	return 0;
-}
+	i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
 
-static int i2ob_revalidate(struct gendisk *disk)
-{
-	struct i2ob_device *p = disk->private_data;
-	return i2ob_install_device(p->controller, p->i2odev, p->index);
-}
+	add_disk(gd);
 
-/*
- * Reboot notifier.  This is called by i2o_core when the system
- * shuts down.
- */
-static void i2ob_reboot_event(void)
-{
-	int i;
-	
-	for(i=0;i<MAX_I2OB;i++)
-	{
-		struct i2ob_device *dev=&i2ob_dev[i];
-		
-		if(dev->refcnt!=0)
-		{
-			/*
-			 *	Flush the onboard cache
-			 */
-			u32 msg[5];
-			int *query_done = &dev->done_flag;
-			msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-			msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid;
-			msg[2] = i2ob_context|0x40000000;
-			msg[3] = (u32)query_done;
-			msg[4] = 60<<16;
-			
-			DEBUG("Flushing...");
-			i2o_post_wait(dev->controller, msg, 20, 60);
+	unit++;
 
-			DEBUG("Unlocking...");
-			/*
-			 *	Unlock the media
-			 */
-			msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-			msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid;
-			msg[2] = i2ob_context|0x40000000;
-			msg[3] = (u32)query_done;
-			msg[4] = -1;
-			i2o_post_wait(dev->controller, msg, 20, 2);
-			
-			DEBUG("Unlocked.\n");
-		}
-	}	
-}
+	return 0;
 
-static struct block_device_operations i2ob_fops =
-{
-	.owner		= THIS_MODULE,
-	.open		= i2ob_open,
-	.release	= i2ob_release,
-	.ioctl		= i2ob_ioctl,
-	.media_changed	= i2ob_media_change,
-	.revalidate_disk= i2ob_revalidate,
+      claim_release:
+	i2o_device_claim_release(i2o_dev);
+
+      exit:
+	return rc;
 };
 
-/*
- * And here should be modules and kernel interface 
- *  (Just smiley confuses emacs :-)
- */
+/* Block OSM driver struct */
+static struct i2o_driver i2o_block_driver = {
+	.name = "block-osm",
+	.event = i2o_block_event,
+	.reply = i2o_block_reply,
+	.classes = i2o_block_class_id,
+	.driver = {
+		   .probe = i2o_block_probe,
+		   .remove = i2o_block_remove,
+		   },
+};
 
-static int i2o_block_init(void)
+/**
+ *	i2o_block_init - Block OSM initialization function
+ *
+ *	Allocate the slab and mempool for request structs, registers i2o_block
+ *	block device and finally register the Block OSM in the I2O core.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_block_init(void)
 {
-	int i;
+	int rc;
+	int size;
 
 	printk(KERN_INFO "I2O Block Storage OSM v0.9\n");
 	printk(KERN_INFO "   (c) Copyright 1999-2001 Red Hat Software.\n");
-	
-	/*
-	 *	Register the block device interfaces
-	 */
-	if (register_blkdev(MAJOR_NR, "i2o_block"))
-		return -EIO;
 
+	/* Allocate request mempool and slab */
+	size = sizeof(struct i2o_block_request);
+	i2o_blk_req_pool.slab = kmem_cache_create("i2o_block_req", size, 0,
+						  SLAB_HWCACHE_ALIGN, NULL,
+						  NULL);
+	if (!i2o_blk_req_pool.slab) {
+		printk(KERN_ERR "block-osm: can't init request slab\n");
+		rc = -ENOMEM;
+		goto exit;
+	}
+
+	i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE,
+					       mempool_alloc_slab,
+					       mempool_free_slab,
+					       i2o_blk_req_pool.slab);
+	if (!i2o_blk_req_pool.pool) {
+		printk(KERN_ERR "block-osm: can't init request mempool\n");
+		rc = -ENOMEM;
+		goto free_slab;
+	}
+
+	/* Register the block device interfaces */
+	rc = register_blkdev(I2O_MAJOR, "i2o_block");
+	if (rc) {
+		printk(KERN_ERR "block-osm: unable to register block device\n");
+		goto free_mempool;
+	}
 #ifdef MODULE
-	printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR);
+	printk(KERN_INFO "block-osm: registered device at major %d\n",
+	       I2O_MAJOR);
 #endif
 
-	/*
-	 *	Set up the queue
-	 */
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-		i2ob_queues[i] = NULL;
-
-	/*
-	 *	Now fill in the boiler plate
-	 */
-	 
-	for (i = 0; i < MAX_I2OB; i++) {
-		struct i2ob_device *dev = &i2ob_dev[i];
-		dev->index = i;
-		dev->refcnt = 0;
-		dev->flags = 0;
-		dev->controller = NULL;
-		dev->i2odev = NULL;
-		dev->tid = 0;
-		dev->head = NULL;
-		dev->tail = NULL;
-		dev->depth = MAX_I2OB_DEPTH;
-		dev->max_sectors = 2;
-		dev->gd = NULL;
-	}
-	
-	/*
-	 *	Register the OSM handler as we will need this to probe for
-	 *	drives, geometry and other goodies.
-	 */
-
-	if(i2o_install_handler(&i2o_block_handler)<0)
-	{
-		unregister_blkdev(MAJOR_NR, "i2o_block");
-		printk(KERN_ERR "i2o_block: unable to register OSM.\n");
-		return -EINVAL;
-	}
-	i2ob_context = i2o_block_handler.context;	 
-
-	/*
-	 * Initialize event handling thread
-	 */
-	init_MUTEX_LOCKED(&i2ob_evt_sem);
-	evt_pid = kernel_thread(i2ob_evt, NULL, CLONE_SIGHAND);
-	if(evt_pid < 0)
-	{
-		printk(KERN_ERR "i2o_block: Could not initialize event thread.  Aborting\n");
-		i2o_remove_handler(&i2o_block_handler);
-		return 0;
+	/* Register Block OSM into I2O core */
+	rc = i2o_driver_register(&i2o_block_driver);
+	if (rc) {
+		printk(KERN_ERR "block-osm: Could not register Block driver\n");
+		goto unregister_blkdev;
 	}
 
-	i2ob_probe();
-
 	return 0;
 
-	unregister_blkdev(MAJOR_NR, "i2o_block");
-	return -ENOMEM;
-}
+      unregister_blkdev:
+	unregister_blkdev(I2O_MAJOR, "i2o_block");
 
+      free_mempool:
+	mempool_destroy(i2o_blk_req_pool.pool);
 
-static void i2o_block_exit(void)
-{
-	int i;
-	
-	if(evt_running) {
-		printk(KERN_INFO "Killing I2O block threads...");
-		i = kill_proc(evt_pid, SIGKILL, 1);
-		if(!i) {
-			printk("waiting...\n");
-		}
-		/* Be sure it died */
-		wait_for_completion(&i2ob_thread_dead);
-		printk("done.\n");
-	}
+      free_slab:
+	kmem_cache_destroy(i2o_blk_req_pool.slab);
 
-	/*
-	 * Unregister for updates from any devices..otherwise we still
-	 * get them and the core jumps to random memory :O
-	 */
-	if(i2ob_dev_count) {
-		struct i2o_device *d;
-		for(i = 0; i < MAX_I2OB; i++)
-			if((d = i2ob_dev[i].i2odev))
-				i2ob_del_device(d->controller, d);
-	}
-	
-	/*
-	 *	We may get further callbacks for ourself. The i2o_core
-	 *	code handles this case reasonably sanely. The problem here
-	 *	is we shouldn't get them .. but a couple of cards feel 
-	 *	obliged to tell us stuff we don't care about.
-	 *
-	 *	This isnt ideal at all but will do for now.
-	 */
-	 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
-	
-	/*
-	 *	Flush the OSM
-	 */
+      exit:
+	return rc;
+};
 
-	i2o_remove_handler(&i2o_block_handler);
+/**
+ *	i2o_block_exit - Block OSM exit function
+ *
+ *	Unregisters Block OSM from I2O core, unregisters i2o_block block device
+ *	and frees the mempool and slab.
+ */
+static void __exit i2o_block_exit(void)
+{
+	/* Unregister I2O Block OSM from I2O core */
+	i2o_driver_unregister(&i2o_block_driver);
 
-	/*
-	 *	Return the block device
-	 */
-	if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0)
-		printk("i2o_block: cleanup_module failed\n");
+	/* Unregister block device */
+	unregister_blkdev(I2O_MAJOR, "i2o_block");
 
-	/*
-	 *	release request queue
-	 */
-	for (i = 0; i < MAX_I2O_CONTROLLERS; i ++)
-		if(i2ob_queues[i]) {
-			blk_cleanup_queue(i2ob_queues[i]->req_queue);
-			kfree(i2ob_queues[i]);
-		}
-}
+	/* Free request mempool and slab */
+	mempool_destroy(i2o_blk_req_pool.pool);
+	kmem_cache_destroy(i2o_blk_req_pool.slab);
+};
 
 MODULE_AUTHOR("Red Hat");
 MODULE_DESCRIPTION("I2O Block Device OSM");
diff -Nru a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/message/i2o/i2o_block.h	2004-08-24 11:29:32 -07:00
@@ -0,0 +1,99 @@
+/*
+ *	Block OSM structures/API
+ *
+ * 	Copyright (C) 1999-2002	Red Hat Software
+ *
+ *	Written by Alan Cox, Building Number Three Ltd
+ *
+ *	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 of the License, 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.
+ *
+ *	For the purpose of avoiding doubt the preferred form of the work
+ *	for making modifications shall be a standards compliant form such
+ *	gzipped tar and not one requiring a proprietary or patent encumbered
+ *	tool to unpack.
+ *
+ *	Fixes/additions:
+ *		Steve Ralston:
+ *			Multiple device handling error fixes,
+ *			Added a queue depth.
+ *		Alan Cox:
+ *			FC920 has an rmw bug. Dont or in the end marker.
+ *			Removed queue walk, fixed for 64bitness.
+ *			Rewrote much of the code over time
+ *			Added indirect block lists
+ *			Handle 64K limits on many controllers
+ *			Don't use indirects on the Promise (breaks)
+ *			Heavily chop down the queue depths
+ *		Deepak Saxena:
+ *			Independent queues per IOP
+ *			Support for dynamic device creation/deletion
+ *			Code cleanup
+ *	    		Support for larger I/Os through merge* functions
+ *			(taken from DAC960 driver)
+ *		Boji T Kannanthanam:
+ *			Set the I2O Block devices to be detected in increasing
+ *			order of TIDs during boot.
+ *			Search and set the I2O block device that we boot off
+ *			from as the first device to be claimed (as /dev/i2o/hda)
+ *			Properly attach/detach I2O gendisk structure from the
+ *			system gendisk list. The I2O block devices now appear in
+ *			/proc/partitions.
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *			Minor bugfixes for 2.6.
+ */
+
+#ifndef I2O_BLOCK_OSM_H
+#define I2O_BLOCK_OSM_H
+
+#define I2O_BLOCK_RETRY_TIME HZ/4
+#define I2O_BLOCK_MAX_OPEN_REQUESTS 50
+
+/* I2O Block OSM mempool struct */
+struct i2o_block_mempool {
+	kmem_cache_t	*slab;
+	mempool_t	*pool;
+};
+
+/* I2O Block device descriptor */
+struct i2o_block_device {
+	struct i2o_device *i2o_dev;	/* pointer to I2O device */
+	struct gendisk *gd;
+	spinlock_t lock;		/* queue lock */
+	struct list_head open_queue;	/* list of transfered, but unfinished
+					   requests */
+	unsigned int open_queue_depth;	/* number of requests in the queue */
+
+	int rcache;			/* read cache flags */
+	int wcache;			/* write cache flags */
+	int flags;
+	int power;			/* power state */
+	int media_change_flag;		/* media changed flag */
+};
+
+/* I2O Block device request */
+struct i2o_block_request
+{
+	struct list_head queue;
+	struct request *req;		/* corresponding request */
+	struct i2o_block_device *i2o_blk_dev;	/* I2O block device */
+	int sg_dma_direction;		/* direction of DMA buffer read/write */
+	int sg_nents;			/* number of SG elements */
+	struct scatterlist sg_table[I2O_MAX_SEGMENTS]; /* SG table */
+};
+
+/* I2O Block device delayed request */
+struct i2o_block_delayed_request
+{
+	struct work_struct work;
+	struct request_queue *queue;
+};
+
+#endif
diff -Nru a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
--- a/drivers/message/i2o/i2o_config.c	2004-07-12 01:01:06 -07:00
+++ b/drivers/message/i2o/i2o_config.c	2004-08-19 09:24:05 -07:00
@@ -2,7 +2,7 @@
  * I2O Configuration Interface Driver
  *
  * (C) Copyright 1999-2002  Red Hat
- *	
+ *
  * Written by Alan Cox, Building Number Three Ltd
  *
  * Fixes/additions:
@@ -41,63 +41,53 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
+#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-static int i2o_cfg_context = -1;
-static void *page_buf;
+extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+
 static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
 struct wait_queue *i2o_wait_queue;
 
 #define MODINC(x,y) ((x) = ((x) + 1) % (y))
 
 struct sg_simple_element {
-	u32  flag_count;
+	u32 flag_count;
 	u32 addr_bus;
 };
 
-struct i2o_cfg_info
-{
-	struct file* fp;
+struct i2o_cfg_info {
+	struct file *fp;
 	struct fasync_struct *fasync;
 	struct i2o_evt_info event_q[I2O_EVT_Q_LEN];
-	u16		q_in;		// Queue head index
-	u16		q_out;		// Queue tail index
-	u16		q_len;		// Queue length
-	u16		q_lost;		// Number of lost events
-	u32		q_id;		// Event queue ID...used as tx_context
-	struct	i2o_cfg_info *next;
+	u16 q_in;		// Queue head index
+	u16 q_out;		// Queue tail index
+	u16 q_len;		// Queue length
+	u16 q_lost;		// Number of lost events
+	ulong q_id;		// Event queue ID...used as tx_context
+	struct i2o_cfg_info *next;
 };
 static struct i2o_cfg_info *open_files = NULL;
-static int i2o_cfg_info_id = 0;
-
-static int ioctl_getiops(unsigned long);
-static int ioctl_gethrt(unsigned long);
-static int ioctl_getlct(unsigned long);
-static int ioctl_parms(unsigned long, unsigned int);
-static int ioctl_html(unsigned long);
-static int ioctl_swdl(unsigned long);
-static int ioctl_swul(unsigned long);
-static int ioctl_swdel(unsigned long);
-static int ioctl_validate(unsigned long); 
-static int ioctl_evt_reg(unsigned long, struct file *);
-static int ioctl_evt_get(unsigned long, struct file *);
-static int ioctl_passthru(unsigned long);
-static int cfg_fasync(int, struct file*, int);
+static ulong i2o_cfg_info_id = 0;
 
+#if 0
 /*
  *	This is the callback for any message we have posted. The message itself
  *	will be returned to the message pool when we return from the IRQ
  *
  *	This runs in irq context so be short and sweet.
  */
-static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m)
+static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c,
+			  struct i2o_message *m)
 {
-	u32 *msg = (u32 *)m;
+	u32 *msg = (u32 *) m;
 
 	if (msg[0] & MSG_FAIL) {
-		u32 *preserved_msg = (u32*)(c->msg_virt + msg[7]);
+		u32 *preserved_msg = (u32 *) (c->msg_virt + msg[7]);
 
 		printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");
 
@@ -109,26 +99,25 @@
 		i2o_post_message(c, msg[7]);
 	}
 
-	if (msg[4] >> 24)  // ReqStatus != SUCCESS
-		i2o_report_status(KERN_INFO,"i2o_config", msg);
+	if (msg[4] >> 24)	// ReqStatus != SUCCESS
+		i2o_report_status(KERN_INFO, "i2o_config", msg);
 
-	if(m->function == I2O_CMD_UTIL_EVT_REGISTER)
-	{
+	if (m->function == I2O_CMD_UTIL_EVT_REGISTER) {
 		struct i2o_cfg_info *inf;
 
-		for(inf = open_files; inf; inf = inf->next)
-			if(inf->q_id == msg[3])
+		for (inf = open_files; inf; inf = inf->next)
+			if (inf->q_id == i2o_cntxt_list_get(c, msg[3]))
 				break;
 
 		//
 		// If this is the case, it means that we're getting
 		// events for a file descriptor that's been close()'d
 		// w/o the user unregistering for events first.
-		// The code currently assumes that the user will 
+		// The code currently assumes that the user will
 		// take care of unregistering for events before closing
 		// a file.
-		// 
-		// TODO: 
+		//
+		// TODO:
 		// Should we track event registartion and deregister
 		// for events when a file is close()'d so this doesn't
 		// happen? That would get rid of the search through
@@ -137,8 +126,8 @@
 		// it would mean having all sorts of tables to track
 		// what each file is registered for...I think the
 		// current method is simpler. - DS
-		//			
-		if(!inf)
+		//
+		if (!inf)
 			return;
 
 		inf->event_q[inf->q_in].id.iop = c->unit;
@@ -149,278 +138,167 @@
 		// Data size = msg size - reply header
 		//
 		inf->event_q[inf->q_in].data_size = (m->size - 5) * 4;
-		if(inf->event_q[inf->q_in].data_size)
-			memcpy(inf->event_q[inf->q_in].evt_data, 
-				(unsigned char *)(msg + 5),
-				inf->event_q[inf->q_in].data_size);
+		if (inf->event_q[inf->q_in].data_size)
+			memcpy(inf->event_q[inf->q_in].evt_data,
+			       (unsigned char *)(msg + 5),
+			       inf->event_q[inf->q_in].data_size);
 
 		spin_lock(&i2o_config_lock);
 		MODINC(inf->q_in, I2O_EVT_Q_LEN);
-		if(inf->q_len == I2O_EVT_Q_LEN)
-		{
+		if (inf->q_len == I2O_EVT_Q_LEN) {
 			MODINC(inf->q_out, I2O_EVT_Q_LEN);
 			inf->q_lost++;
-		}
-		else
-		{
+		} else {
 			// Keep I2OEVTGET on another CPU from touching this
 			inf->q_len++;
 		}
 		spin_unlock(&i2o_config_lock);
-		
 
-//		printk(KERN_INFO "File %p w/id %d has %d events\n",
-//			inf->fp, inf->q_id, inf->q_len);	
+//              printk(KERN_INFO "File %p w/id %d has %d events\n",
+//                      inf->fp, inf->q_id, inf->q_len);
 
 		kill_fasync(&inf->fasync, SIGIO, POLL_IN);
 	}
 
 	return;
 }
+#endif
 
 /*
  *	Each of these describes an i2o message handler. They are
  *	multiplexed by the i2o_core code
  */
- 
-struct i2o_handler cfg_handler=
-{
-	i2o_cfg_reply,
-	NULL,
-	NULL,
-	NULL,
-	"Configuration",
-	0,
-	0xffffffff	// All classes
-};
-
-static ssize_t cfg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-	printk(KERN_INFO "i2o_config write not yet supported\n");
 
-	return 0;
-}
-
-
-static ssize_t cfg_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
-{
-	return 0;
-}
+struct i2o_driver i2o_config_driver = {
+	.name = "Config-OSM"
+};
 
-/*
- * IOCTL Handler
- */
-static int cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
-	unsigned long arg)
+static int i2o_cfg_getiops(unsigned long arg)
 {
-	int ret;
-
-	switch(cmd)
-	{	
-		case I2OGETIOPS:
-			ret = ioctl_getiops(arg);
-			break;
-
-		case I2OHRTGET:
-			ret = ioctl_gethrt(arg);
-			break;
-
-		case I2OLCTGET:
-			ret = ioctl_getlct(arg);
-			break;
-
-		case I2OPARMSET:
-			ret = ioctl_parms(arg, I2OPARMSET);
-			break;
-
-		case I2OPARMGET:
-			ret = ioctl_parms(arg, I2OPARMGET);
-			break;
-
-		case I2OSWDL:
-			ret = ioctl_swdl(arg);
-			break;
-
-		case I2OSWUL:
-			ret = ioctl_swul(arg);
-			break;
-
-		case I2OSWDEL:
-			ret = ioctl_swdel(arg);
-			break;
-
-		case I2OVALIDATE:
-			ret = ioctl_validate(arg);
-			break;
-			
-		case I2OHTML:
-			ret = ioctl_html(arg);
-			break;
-
-		case I2OEVTREG:
-			ret = ioctl_evt_reg(arg, fp);
-			break;
+	struct i2o_controller *c;
+	u8 __user *user_iop_table = (void __user *)arg;
+	u8 tmp[MAX_I2O_CONTROLLERS];
 
-		case I2OEVTGET:
-			ret = ioctl_evt_get(arg, fp);
-			break;
+	memset(tmp, 0, MAX_I2O_CONTROLLERS);
 
-		case I2OPASSTHRU:
-			ret = ioctl_passthru(arg);
-			break;
+	if (!access_ok(VERIFY_WRITE, user_iop_table, MAX_I2O_CONTROLLERS))
+		return -EFAULT;
 
-		default:
-			ret = -EINVAL;
-	}
+	list_for_each_entry(c, &i2o_controllers, list)
+	    tmp[c->unit] = 1;
 
-	return ret;
-}
+	__copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS);
 
-int ioctl_getiops(unsigned long arg)
-{
-	u8  __user *user_iop_table = (void __user *)arg;
-	struct i2o_controller *c = NULL;
-	int i;
-	u8 foo[MAX_I2O_CONTROLLERS];
-
-	if(!access_ok(VERIFY_WRITE, user_iop_table,  MAX_I2O_CONTROLLERS))
-		return -EFAULT;
-
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-		c = i2o_find_controller(i);
-		if(c)
-		{
-			foo[i] = 1;
-			if(pci_set_dma_mask(c->pdev, 0xffffffff))
-			{
-				printk(KERN_WARNING "i2o_config : No suitable DMA available on controller %d\n", i);
-				i2o_unlock_controller(c);
-				continue;
-			}
-		
-				i2o_unlock_controller(c);
-		}
-		else
-		{
-			foo[i] = 0;
-		}
-	}
-
-	__copy_to_user(user_iop_table, foo, MAX_I2O_CONTROLLERS);
 	return 0;
-}
+};
 
-int ioctl_gethrt(unsigned long arg)
+static int i2o_cfg_gethrt(unsigned long arg)
 {
 	struct i2o_controller *c;
-	struct i2o_cmd_hrtlct __user *cmd = (void __user *)arg;
+	struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg;
 	struct i2o_cmd_hrtlct kcmd;
 	i2o_hrt *hrt;
 	int len;
 	u32 reslen;
 	int ret = 0;
 
-	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
+	if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
 		return -EFAULT;
 
-	if(get_user(reslen, kcmd.reslen) < 0)
+	if (get_user(reslen, kcmd.reslen) < 0)
 		return -EFAULT;
 
-	if(kcmd.resbuf == NULL)
+	if (kcmd.resbuf == NULL)
 		return -EFAULT;
 
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
+	c = i2o_find_iop(kcmd.iop);
+	if (!c)
 		return -ENXIO;
-		
-	hrt = (i2o_hrt *)c->hrt;
 
-	i2o_unlock_controller(c);
+	hrt = (i2o_hrt *) c->hrt.virt;
 
 	len = 8 + ((hrt->entry_len * hrt->num_entries) << 2);
-	
+
 	/* We did a get user...so assuming mem is ok...is this bad? */
 	put_user(len, kcmd.reslen);
-	if(len > reslen)
-		ret = -ENOBUFS;	
-	if(copy_to_user(kcmd.resbuf, (void*)hrt, len))
+	if (len > reslen)
+		ret = -ENOBUFS;
+	if (copy_to_user(kcmd.resbuf, (void *)hrt, len))
 		ret = -EFAULT;
 
 	return ret;
-}
+};
 
-int ioctl_getlct(unsigned long arg)
+static int i2o_cfg_getlct(unsigned long arg)
 {
 	struct i2o_controller *c;
-	struct i2o_cmd_hrtlct __user *cmd = (void __user *)arg;
+	struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg;
 	struct i2o_cmd_hrtlct kcmd;
 	i2o_lct *lct;
 	int len;
 	int ret = 0;
 	u32 reslen;
 
-	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
+	if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
 		return -EFAULT;
 
-	if(get_user(reslen, kcmd.reslen) < 0)
+	if (get_user(reslen, kcmd.reslen) < 0)
 		return -EFAULT;
 
-	if(kcmd.resbuf == NULL)
+	if (kcmd.resbuf == NULL)
 		return -EFAULT;
 
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
+	c = i2o_find_iop(kcmd.iop);
+	if (!c)
 		return -ENXIO;
 
-	lct = (i2o_lct *)c->lct;
-	i2o_unlock_controller(c);
+	lct = (i2o_lct *) c->lct;
 
 	len = (unsigned int)lct->table_size << 2;
 	put_user(len, kcmd.reslen);
-	if(len > reslen)
-		ret = -ENOBUFS;	
-	else if(copy_to_user(kcmd.resbuf, (void*)lct, len))
+	if (len > reslen)
+		ret = -ENOBUFS;
+	else if (copy_to_user(kcmd.resbuf, lct, len))
 		ret = -EFAULT;
 
 	return ret;
-}
+};
 
-static int ioctl_parms(unsigned long arg, unsigned int type)
+static int i2o_cfg_parms(unsigned long arg, unsigned int type)
 {
 	int ret = 0;
 	struct i2o_controller *c;
-	struct i2o_cmd_psetget __user *cmd = (void __user *)arg;
+	struct i2o_device *dev;
+	struct i2o_cmd_psetget __user *cmd =
+	    (struct i2o_cmd_psetget __user *)arg;
 	struct i2o_cmd_psetget kcmd;
 	u32 reslen;
 	u8 *ops;
 	u8 *res;
-	int len;
+	int len = 0;
 
-	u32 i2o_cmd = (type == I2OPARMGET ? 
-				I2O_CMD_UTIL_PARAMS_GET :
-				I2O_CMD_UTIL_PARAMS_SET);
+	u32 i2o_cmd = (type == I2OPARMGET ?
+		       I2O_CMD_UTIL_PARAMS_GET : I2O_CMD_UTIL_PARAMS_SET);
 
-	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget)))
+	if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget)))
 		return -EFAULT;
 
-	if(get_user(reslen, kcmd.reslen))
+	if (get_user(reslen, kcmd.reslen))
 		return -EFAULT;
 
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
+	c = i2o_find_iop(kcmd.iop);
+	if (!c)
 		return -ENXIO;
 
-	ops = (u8*)kmalloc(kcmd.oplen, GFP_KERNEL);
-	if(!ops)
-	{
-		i2o_unlock_controller(c);
+	dev = i2o_iop_find_device(c, kcmd.tid);
+	if (!dev)
+		return -ENXIO;
+
+	ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL);
+	if (!ops)
 		return -ENOMEM;
-	}
 
-	if(copy_from_user(ops, kcmd.opbuf, kcmd.oplen))
-	{
-		i2o_unlock_controller(c);
+	if (copy_from_user(ops, kcmd.opbuf, kcmd.oplen)) {
 		kfree(ops);
 		return -EFAULT;
 	}
@@ -429,404 +307,309 @@
 	 * It's possible to have a _very_ large table
 	 * and that the user asks for all of it at once...
 	 */
-	res = (u8*)kmalloc(65536, GFP_KERNEL);
-	if(!res)
-	{
-		i2o_unlock_controller(c);
+	res = (u8 *) kmalloc(65536, GFP_KERNEL);
+	if (!res) {
 		kfree(ops);
 		return -ENOMEM;
 	}
 
-	len = i2o_issue_params(i2o_cmd, c, kcmd.tid, 
-				ops, kcmd.oplen, res, 65536);
-	i2o_unlock_controller(c);
+	len = i2o_parm_issue(dev, i2o_cmd, ops, kcmd.oplen, res, 65536);
 	kfree(ops);
-        
+
 	if (len < 0) {
 		kfree(res);
 		return -EAGAIN;
 	}
 
 	put_user(len, kcmd.reslen);
-	if(len > reslen)
+	if (len > reslen)
 		ret = -ENOBUFS;
-	else if(copy_to_user(kcmd.resbuf, res, len))
+	else if (copy_to_user(kcmd.resbuf, res, len))
 		ret = -EFAULT;
 
 	kfree(res);
 
 	return ret;
-}
+};
 
-int ioctl_html(unsigned long arg)
+static int i2o_cfg_swdl(unsigned long arg)
 {
-	struct i2o_html __user *cmd = (void __user *)arg;
-	struct i2o_html kcmd;
+	struct i2o_sw_xfer kxfer;
+	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
+	unsigned char maxfrag = 0, curfrag = 1;
+	struct i2o_dma buffer;
+	struct i2o_message *msg;
+	u32 m;
+	unsigned int status = 0, swlen = 0, fragsize = 8192;
 	struct i2o_controller *c;
-	u8 *res = NULL;
-	void *query = NULL;
-	dma_addr_t query_phys, res_phys;
-	int ret = 0;
-	int token;
-	u32 len;
-	u32 reslen;
-	u32 msg[MSG_FRAME_SIZE];
 
-	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_html)))
-	{
-		printk(KERN_INFO "i2o_config: can't copy html cmd\n");
+	if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
 		return -EFAULT;
-	}
 
-	if(get_user(reslen, kcmd.reslen) < 0)
-	{
-		printk(KERN_INFO "i2o_config: can't copy html reslen\n");
+	if (get_user(swlen, kxfer.swlen) < 0)
 		return -EFAULT;
-	}
 
-	if(!kcmd.resbuf)		
-	{
-		printk(KERN_INFO "i2o_config: NULL html buffer\n");
+	if (get_user(maxfrag, kxfer.maxfrag) < 0)
 		return -EFAULT;
-	}
 
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
+	if (get_user(curfrag, kxfer.curfrag) < 0)
+		return -EFAULT;
+
+	if (curfrag == maxfrag)
+		fragsize = swlen - (maxfrag - 1) * 8192;
+
+	if (!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize))
+		return -EFAULT;
+
+	c = i2o_find_iop(kxfer.iop);
+	if (!c)
 		return -ENXIO;
 
-	if(kcmd.qlen) /* Check for post data */
-	{
-		query = pci_alloc_consistent(c->pdev, kcmd.qlen, &query_phys);
-		if(!query)
-		{
-			i2o_unlock_controller(c);
-			return -ENOMEM;
-		}
-		if(copy_from_user(query, kcmd.qbuf, kcmd.qlen))
-		{
-			i2o_unlock_controller(c);
-			printk(KERN_INFO "i2o_config: could not get query\n");
-			pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys);
-			return -EFAULT;
-		}
-	}
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
 
-	res = pci_alloc_consistent(c->pdev, 65536, &res_phys);
-	if(!res)
-	{
-		i2o_unlock_controller(c);
-		pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys);
+	if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
+		i2o_msg_nop(c, m);
 		return -ENOMEM;
 	}
 
-	msg[1] = (I2O_CMD_UTIL_CONFIG_DIALOG << 24)|HOST_TID<<12|kcmd.tid;
-	msg[2] = i2o_cfg_context;
-	msg[3] = 0;
-	msg[4] = kcmd.page;
-	msg[5] = 0xD0000000|65536;
-	msg[6] = res_phys;
-	if(!kcmd.qlen) /* Check for post data */
-		msg[0] = SEVEN_WORD_MSG_SIZE|SGL_OFFSET_5;
-	else
-	{
-		msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
-		msg[5] = 0x50000000|65536;
-		msg[7] = 0xD4000000|(kcmd.qlen);
-		msg[8] = query_phys;
-	}
-	/*
-	Wait for a considerable time till the Controller 
-	does its job before timing out. The controller might
-	take more time to process this request if there are
-	many devices connected to it.
-	*/
-	token = i2o_post_wait_mem(c, msg, 9*4, 400, query, res, query_phys, res_phys, kcmd.qlen, 65536);
-	if(token < 0)
-	{
-		printk(KERN_DEBUG "token = %#10x\n", token);
-		i2o_unlock_controller(c);
-		
-		if(token != -ETIMEDOUT)
-		{
-			pci_free_consistent(c->pdev, 65536, res, res_phys);
-			if(kcmd.qlen)
-				pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys);
-		}
-		return token;
-	}
-	i2o_unlock_controller(c);
+	__copy_from_user(buffer.virt, kxfer.buf, fragsize);
 
-	len = strnlen(res, 65536);
-	put_user(len, kcmd.reslen);
-	if(len > reslen)
-		ret = -ENOMEM;
-	if(copy_to_user(kcmd.resbuf, res, len))
-		ret = -EFAULT;
+	writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
+	writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+	writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) |
+	       (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]);
+	writel(swlen, &msg->body[1]);
+	writel(kxfer.sw_id, &msg->body[2]);
+	writel(0xD0000000 | fragsize, &msg->body[3]);
+	writel(buffer.phys, &msg->body[4]);
 
-	pci_free_consistent(c->pdev, 65536, res, res_phys);
-	if(kcmd.qlen)
-		pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys);
+//      printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
+	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
 
-	return ret;
-}
- 
-int ioctl_swdl(unsigned long arg)
+	if (status != -ETIMEDOUT)
+		i2o_dma_free(&c->pdev->dev, &buffer);
+
+	if (status != I2O_POST_WAIT_OK) {
+		// it fails if you try and send frags out of order
+		// and for some yet unknown reasons too
+		printk(KERN_INFO
+		       "i2o_config: swdl failed, DetailedStatus = %d\n",
+		       status);
+		return status;
+	}
+
+	return 0;
+};
+
+static int i2o_cfg_swul(unsigned long arg)
 {
 	struct i2o_sw_xfer kxfer;
-	struct i2o_sw_xfer __user *pxfer = (void __user *)arg;
+	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
 	unsigned char maxfrag = 0, curfrag = 1;
-	unsigned char *buffer;
-	u32 msg[9];
+	struct i2o_dma buffer;
+	struct i2o_message *msg;
+	u32 m;
 	unsigned int status = 0, swlen = 0, fragsize = 8192;
 	struct i2o_controller *c;
-	dma_addr_t buffer_phys;
 
-	if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
+	if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
 		return -EFAULT;
 
-	if(get_user(swlen, kxfer.swlen) < 0)
+	if (get_user(swlen, kxfer.swlen) < 0)
 		return -EFAULT;
 
-	if(get_user(maxfrag, kxfer.maxfrag) < 0)
+	if (get_user(maxfrag, kxfer.maxfrag) < 0)
 		return -EFAULT;
 
-	if(get_user(curfrag, kxfer.curfrag) < 0)
+	if (get_user(curfrag, kxfer.curfrag) < 0)
 		return -EFAULT;
 
-	if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192;
+	if (curfrag == maxfrag)
+		fragsize = swlen - (maxfrag - 1) * 8192;
 
-	if(!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize))
+	if (!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize))
 		return -EFAULT;
-	
-	c = i2o_find_controller(kxfer.iop);
-	if(!c)
+
+	c = i2o_find_iop(kxfer.iop);
+	if (!c)
 		return -ENXIO;
 
-	buffer=pci_alloc_consistent(c->pdev, fragsize, &buffer_phys);
-	if (buffer==NULL)
-	{
-		i2o_unlock_controller(c);
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
+		i2o_msg_nop(c, m);
 		return -ENOMEM;
 	}
-	__copy_from_user(buffer, kxfer.buf, fragsize);
 
-	msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
-	msg[1]= I2O_CMD_SW_DOWNLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2]= (u32)cfg_handler.context;
-	msg[3]= 0;
-	msg[4]= (((u32)kxfer.flags)<<24) | (((u32)kxfer.sw_type)<<16) |
-		(((u32)maxfrag)<<8) | (((u32)curfrag));
-	msg[5]= swlen;
-	msg[6]= kxfer.sw_id;
-	msg[7]= (0xD0000000 | fragsize);
-	msg[8]= buffer_phys;
-
-//	printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
-	status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL, buffer_phys, 0, fragsize, 0);
-
-	i2o_unlock_controller(c);
-	if(status != -ETIMEDOUT)
-		pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys);
-	
-	if (status != I2O_POST_WAIT_OK)
-	{
-		// it fails if you try and send frags out of order
-		// and for some yet unknown reasons too
-		printk(KERN_INFO "i2o_config: swdl failed, DetailedStatus = %d\n", status);
+	writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
+	writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+	writel((u32) kxfer.flags << 24 | (u32) kxfer.
+	       sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag,
+	       &msg->body[0]);
+	writel(swlen, &msg->body[1]);
+	writel(kxfer.sw_id, &msg->body[2]);
+	writel(0xD0000000 | fragsize, &msg->body[3]);
+	writel(buffer.phys, &msg->body[4]);
+
+//      printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
+	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+
+	if (status != I2O_POST_WAIT_OK) {
+		if (status != -ETIMEDOUT)
+			i2o_dma_free(&c->pdev->dev, &buffer);
+
+		printk(KERN_INFO
+		       "i2o_config: swul failed, DetailedStatus = %d\n",
+		       status);
 		return status;
 	}
 
-	return 0;
-}
+	__copy_to_user(kxfer.buf, buffer.virt, fragsize);
+	i2o_dma_free(&c->pdev->dev, &buffer);
 
-int ioctl_swul(unsigned long arg)
-{
-	struct i2o_sw_xfer kxfer;
-	struct i2o_sw_xfer __user *pxfer = (void __user *)arg;
-	unsigned char maxfrag = 0, curfrag = 1;
-	unsigned char *buffer;
-	u32 msg[9];
-	unsigned int status = 0, swlen = 0, fragsize = 8192;
-	struct i2o_controller *c;
-	dma_addr_t buffer_phys;
-		
-	if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
-		return -EFAULT;
-		
-	if(get_user(swlen, kxfer.swlen) < 0)
-		return -EFAULT;
-		
-	if(get_user(maxfrag, kxfer.maxfrag) < 0)
-		return -EFAULT;
-		
-	if(get_user(curfrag, kxfer.curfrag) < 0)
-		return -EFAULT;
-	
-	if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192;
-	
-	if(!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize))
-		return -EFAULT;
-		
-	c = i2o_find_controller(kxfer.iop);
-	if(!c)
-		return -ENXIO;
-		
-	buffer=pci_alloc_consistent(c->pdev, fragsize, &buffer_phys);
-	if (buffer==NULL)
-	{
-		i2o_unlock_controller(c);
-		return -ENOMEM;
-	}
-	
-	msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
-	msg[1]= I2O_CMD_SW_UPLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2]= (u32)cfg_handler.context;
-	msg[3]= 0;
-	msg[4]= (u32)kxfer.flags<<24|(u32)kxfer.sw_type<<16|(u32)maxfrag<<8|(u32)curfrag;
-	msg[5]= swlen;
-	msg[6]= kxfer.sw_id;
-	msg[7]= (0xD0000000 | fragsize);
-	msg[8]= buffer_phys;
-	
-//	printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
-	status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL, buffer_phys, 0, fragsize, 0);
-	i2o_unlock_controller(c);
-	
-	if (status != I2O_POST_WAIT_OK)
-	{
-		if(status != -ETIMEDOUT)
-			pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys);
-		printk(KERN_INFO "i2o_config: swul failed, DetailedStatus = %d\n", status);
-		return status;
-	}
-	
-	__copy_to_user(kxfer.buf, buffer, fragsize);
-	pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys);
-	
 	return 0;
-}
+};
 
-int ioctl_swdel(unsigned long arg)
+static int i2o_cfg_swdel(unsigned long arg)
 {
 	struct i2o_controller *c;
 	struct i2o_sw_xfer kxfer;
-	struct i2o_sw_xfer __user *pxfer = (void __user *)arg;
-	u32 msg[7];
+	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
+	struct i2o_message *msg;
+	u32 m;
 	unsigned int swlen;
 	int token;
-	
+
 	if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
 		return -EFAULT;
-		
+
 	if (get_user(swlen, kxfer.swlen) < 0)
 		return -EFAULT;
-		
-	c = i2o_find_controller(kxfer.iop);
+
+	c = i2o_find_iop(kxfer.iop);
 	if (!c)
 		return -ENXIO;
 
-	msg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
-	msg[1] = I2O_CMD_SW_REMOVE<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2] = (u32)i2o_cfg_context;
-	msg[3] = 0;
-	msg[4] = (u32)kxfer.flags<<24 | (u32)kxfer.sw_type<<16;
-	msg[5] = swlen;
-	msg[6] = kxfer.sw_id;
-
-	token = i2o_post_wait(c, msg, sizeof(msg), 10);
-	i2o_unlock_controller(c);
-	
-	if (token != I2O_POST_WAIT_OK)
-	{
-		printk(KERN_INFO "i2o_config: swdel failed, DetailedStatus = %d\n", token);
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+	writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16,
+	       &msg->body[0]);
+	writel(swlen, &msg->body[1]);
+	writel(kxfer.sw_id, &msg->body[2]);
+
+	token = i2o_msg_post_wait(c, m, 10);
+
+	if (token != I2O_POST_WAIT_OK) {
+		printk(KERN_INFO
+		       "i2o_config: swdel failed, DetailedStatus = %d\n",
+		       token);
 		return -ETIMEDOUT;
 	}
-	
+
 	return 0;
-}
+};
 
-int ioctl_validate(unsigned long arg)
+static int i2o_cfg_validate(unsigned long arg)
 {
-        int token;
-        int iop = (int)arg;
-        u32 msg[4];
-        struct i2o_controller *c;
-
-        c=i2o_find_controller(iop);
-        if (!c)
-                return -ENXIO;
-
-        msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-        msg[1] = I2O_CMD_CONFIG_VALIDATE<<24 | HOST_TID<<12 | iop;
-        msg[2] = (u32)i2o_cfg_context;
-        msg[3] = 0;
-
-        token = i2o_post_wait(c, msg, sizeof(msg), 10);
-        i2o_unlock_controller(c);
-
-        if (token != I2O_POST_WAIT_OK)
-        {
-                printk(KERN_INFO "Can't validate configuration, ErrorStatus = %d\n",
-                	token);
-                return -ETIMEDOUT;
-        }
+	int token;
+	int iop = (int)arg;
+	struct i2o_message *msg;
+	u32 m;
+	struct i2o_controller *c;
+
+	c = i2o_find_iop(iop);
+	if (!c)
+		return -ENXIO;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
 
-        return 0;
-}   
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+
+	token = i2o_msg_post_wait(c, m, 10);
+
+	if (token != I2O_POST_WAIT_OK) {
+		printk(KERN_INFO "Can't validate configuration, ErrorStatus = "
+		       "%d\n", token);
+		return -ETIMEDOUT;
+	}
 
-static int ioctl_evt_reg(unsigned long arg, struct file *fp)
+	return 0;
+};
+
+static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
 {
-	u32 msg[5];
-	struct i2o_evt_id __user *pdesc = (void __user *)arg;
+	struct i2o_message *msg;
+	u32 m;
+	struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg;
 	struct i2o_evt_id kdesc;
-	struct i2o_controller *iop;
+	struct i2o_controller *c;
 	struct i2o_device *d;
 
 	if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id)))
 		return -EFAULT;
 
 	/* IOP exists? */
-	iop = i2o_find_controller(kdesc.iop);
-	if(!iop)
+	c = i2o_find_iop(kdesc.iop);
+	if (!c)
 		return -ENXIO;
-	i2o_unlock_controller(iop);
 
 	/* Device exists? */
-	for(d = iop->devices; d; d = d->next)
-		if(d->lct_data.tid == kdesc.tid)
-			break;
-
-	if(!d)
+	d = i2o_iop_find_device(c, kdesc.tid);
+	if (!d)
 		return -ENODEV;
 
-	msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | kdesc.tid;
-	msg[2] = (u32)i2o_cfg_context;
-	msg[3] = (u32)fp->private_data;
-	msg[4] = kdesc.evt_mask;
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]);
+	writel(kdesc.evt_mask, &msg->body[0]);
 
-	i2o_post_this(iop, msg, 20);
+	i2o_msg_post(c, m);
 
 	return 0;
-}	
+}
 
-static int ioctl_evt_get(unsigned long arg, struct file *fp)
+static int i2o_cfg_evt_get(unsigned long arg, struct file *fp)
 {
-	u32 id = (u32)fp->private_data;
 	struct i2o_cfg_info *p = NULL;
-	struct i2o_evt_get __user *uget = (void __user *)arg;
+	struct i2o_evt_get __user *uget = (struct i2o_evt_get __user *)arg;
 	struct i2o_evt_get kget;
 	unsigned long flags;
 
-	for(p = open_files; p; p = p->next)
-		if(p->q_id == id)
+	for (p = open_files; p; p = p->next)
+		if (p->q_id == (ulong) fp->private_data)
 			break;
 
-	if(!p->q_len)
-	{
+	if (!p->q_len)
 		return -ENOENT;
-		return 0;
-	}
 
 	memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
 	MODINC(p->q_out, I2O_EVT_Q_LEN);
@@ -836,16 +619,236 @@
 	kget.lost = p->q_lost;
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
 
-	if(copy_to_user(uget, &kget, sizeof(struct i2o_evt_get)))
+	if (copy_to_user(uget, &kget, sizeof(struct i2o_evt_get)))
 		return -EFAULT;
 	return 0;
 }
 
-static int ioctl_passthru(unsigned long arg)
+#if BITS_PER_LONG == 64
+static int i2o_cfg_passthru32(unsigned fd, unsigned cmnd, unsigned long arg,
+			      struct file *file)
 {
-	struct i2o_cmd_passthru __user *cmd = (void __user *) arg;
+	struct i2o_cmd_passthru32 __user *cmd;
+	struct i2o_controller *c;
+	u32 *user_msg;
+	u32 *reply = NULL;
+	u32 *user_reply = NULL;
+	u32 size = 0;
+	u32 reply_size = 0;
+	u32 rcode = 0;
+	struct i2o_dma sg_list[SG_TABLESIZE];
+	u32 sg_offset = 0;
+	u32 sg_count = 0;
+	u32 i = 0;
+	i2o_status_block *sb;
+	struct i2o_message *msg;
+	u32 m;
+	unsigned int iop;
+
+	cmd = (struct i2o_cmd_passthru32 __user *)arg;
+
+	if (get_user(iop, &cmd->iop) || get_user(i, &cmd->msg))
+		return -EFAULT;
+
+	user_msg = compat_ptr(i);
+
+	c = i2o_find_iop(iop);
+	if (!c) {
+		pr_debug("controller %d not found\n", iop);
+		return -ENXIO;
+	}
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+
+	sb = c->status_block.virt;
+
+	if (get_user(size, &user_msg[0])) {
+		printk(KERN_WARNING "unable to get size!\n");
+		return -EFAULT;
+	}
+	size = size >> 16;
+
+	if (size > sb->inbound_frame_size) {
+		pr_debug("size of message > inbound_frame_size");
+		return -EFAULT;
+	}
+
+	user_reply = &user_msg[size];
+
+	size <<= 2;		// Convert to bytes
+
+	/* Copy in the user's I2O command */
+	if (copy_from_user(msg, user_msg, size)) {
+		printk(KERN_WARNING "unable to copy user message\n");
+		return -EFAULT;
+	}
+	i2o_dump_message(msg);
+
+	if (get_user(reply_size, &user_reply[0]) < 0)
+		return -EFAULT;
+
+	reply_size >>= 16;
+	reply_size <<= 2;
+
+	reply = kmalloc(reply_size, GFP_KERNEL);
+	if (!reply) {
+		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
+		       c->name);
+		return -ENOMEM;
+	}
+	memset(reply, 0, reply_size);
+
+	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
+
+	writel(i2o_config_driver.context, &msg->u.s.icntxt);
+	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
+
+	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
+	if (sg_offset) {
+		struct sg_simple_element *sg;
+
+		if (sg_offset * 4 >= size) {
+			rcode = -EFAULT;
+			goto cleanup;
+		}
+		// TODO 64bit fix
+		sg = (struct sg_simple_element *)((&msg->u.head[0]) +
+						  sg_offset);
+		sg_count =
+		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
+		if (sg_count > SG_TABLESIZE) {
+			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
+			       c->name, sg_count);
+			kfree(reply);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < sg_count; i++) {
+			int sg_size;
+			struct i2o_dma *p;
+
+			if (!(sg[i].flag_count & 0x10000000
+			      /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {
+				printk(KERN_DEBUG
+				       "%s:Bad SG element %d - not simple (%x)\n",
+				       c->name, i, sg[i].flag_count);
+				rcode = -EINVAL;
+				goto cleanup;
+			}
+			sg_size = sg[i].flag_count & 0xffffff;
+			p = &(sg_list[i]);
+			/* Allocate memory for the transfer */
+			if (i2o_dma_alloc
+			    (&c->pdev->dev, p, sg_size,
+			     PCI_DMA_BIDIRECTIONAL)) {
+				printk(KERN_DEBUG
+				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+				       c->name, sg_size, i, sg_count);
+				rcode = -ENOMEM;
+				goto cleanup;
+			}
+			/* Copy in the user's SG buffer if necessary */
+			if (sg[i].
+			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
+				// TODO 64bit fix
+				if (copy_from_user
+				    (p->virt, (void *)(u64) sg[i].addr_bus,
+				     sg_size)) {
+					printk(KERN_DEBUG
+					       "%s: Could not copy SG buf %d FROM user\n",
+					       c->name, i);
+					rcode = -EFAULT;
+					goto cleanup;
+				}
+			}
+			//TODO 64bit fix
+			sg[i].addr_bus = (u32) p->phys;
+		}
+	}
+
+	rcode = i2o_msg_post_wait(c, m, 60);
+	if (rcode)
+		goto cleanup;
+
+	if (sg_offset) {
+		u32 msg[128];
+		/* Copy back the Scatter Gather buffers back to user space */
+		u32 j;
+		// TODO 64bit fix
+		struct sg_simple_element *sg;
+		int sg_size;
+		printk(KERN_INFO "sg_offset\n");
+
+		// re-acquire the original message to handle correctly the sg copy operation
+		memset(&msg, 0, MSG_FRAME_SIZE * 4);
+		// get user msg size in u32s
+		if (get_user(size, &user_msg[0])) {
+			rcode = -EFAULT;
+			goto cleanup;
+		}
+		size = size >> 16;
+		size *= 4;
+		/* Copy in the user's I2O command */
+		if (copy_from_user(msg, user_msg, size)) {
+			rcode = -EFAULT;
+			goto cleanup;
+		}
+		sg_count =
+		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
+
+		// TODO 64bit fix
+		sg = (struct sg_simple_element *)(msg + sg_offset);
+		for (j = 0; j < sg_count; j++) {
+			/* Copy out the SG list to user's buffer if necessary */
+			if (!
+			    (sg[j].
+			     flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {
+				sg_size = sg[j].flag_count & 0xffffff;
+				// TODO 64bit fix
+				if (copy_to_user
+				    ((void __user *)(u64) sg[j].addr_bus,
+				     sg_list[j].virt, sg_size)) {
+					printk(KERN_WARNING
+					       "%s: Could not copy %p TO user %x\n",
+					       c->name, sg_list[j].virt,
+					       sg[j].addr_bus);
+					rcode = -EFAULT;
+					goto cleanup;
+				}
+			}
+		}
+	}
+
+	/* Copy back the reply to user space */
+	if (reply_size) {
+		// we wrote our own values for context - now restore the user supplied ones
+		printk(KERN_INFO "reply_size\n");
+		if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {
+			printk(KERN_WARNING
+			       "%s: Could not copy message context FROM user\n",
+			       c->name);
+			rcode = -EFAULT;
+		}
+		if (copy_to_user(user_reply, reply, reply_size)) {
+			printk(KERN_WARNING
+			       "%s: Could not copy reply TO user\n", c->name);
+			rcode = -EFAULT;
+		}
+	}
+
+      cleanup:
+	kfree(reply);
+	printk(KERN_INFO "rcode: %d\n", rcode);
+	return rcode;
+}
+
+#else
+
+static int i2o_cfg_passthru(unsigned long arg)
+{
+	struct i2o_cmd_passthru __user *cmd =
+	    (struct i2o_cmd_passthru __user *)arg;
 	struct i2o_controller *c;
-	u32 msg[MSG_FRAME_SIZE];
 	u32 __user *user_msg;
 	u32 *reply = NULL;
 	u32 __user *user_reply = NULL;
@@ -858,64 +861,88 @@
 	int sg_index = 0;
 	u32 i = 0;
 	void *p = NULL;
+	i2o_status_block *sb;
+	struct i2o_message *msg;
+	u32 m;
 	unsigned int iop;
 
 	if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))
 		return -EFAULT;
 
-	c = i2o_find_controller(iop);
-	if (!c)
-                return -ENXIO;
+	c = i2o_find_iop(iop);
+	if (!c) {
+		pr_debug("controller %d not found\n", iop);
+		return -ENXIO;
+	}
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+
+	sb = c->status_block.virt;
 
-	memset(&msg, 0, MSG_FRAME_SIZE*4);
-	if(get_user(size, &user_msg[0]))
+	if (get_user(size, &user_msg[0]))
 		return -EFAULT;
-	size = size>>16;
+	size = size >> 16;
 
-	user_reply = &user_msg[size];
-	if(size > MSG_FRAME_SIZE)
+	if (size > sb->inbound_frame_size) {
+		pr_debug("size of message > inbound_frame_size");
 		return -EFAULT;
-	size *= 4; // Convert to bytes
+	}
+
+	user_reply = &user_msg[size];
+
+	size <<= 2;		// Convert to bytes
 
 	/* Copy in the user's I2O command */
-	if(copy_from_user(msg, user_msg, size))
+	if (copy_from_user(msg, user_msg, size))
 		return -EFAULT;
-	if(get_user(reply_size, &user_reply[0]) < 0)
+
+	if (get_user(reply_size, &user_reply[0]) < 0)
 		return -EFAULT;
 
-	reply_size = reply_size>>16;
-	reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
-	if(!reply) {
-		printk(KERN_WARNING"%s: Could not allocate reply buffer\n",c->name);
+	reply_size >>= 16;
+	reply_size <<= 2;
+
+	reply = kmalloc(reply_size, GFP_KERNEL);
+	if (!reply) {
+		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
+		       c->name);
 		return -ENOMEM;
 	}
-	memset(reply, 0, REPLY_FRAME_SIZE*4);
-	sg_offset = (msg[0]>>4)&0x0f;
-	msg[2] = (u32)i2o_cfg_context;
-	msg[3] = (u32)reply;
+	memset(reply, 0, reply_size);
+
+	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
 
-	memset(sg_list,0, sizeof(sg_list[0])*SG_TABLESIZE);
-	if(sg_offset) {
+	writel(i2o_config_driver.context, &msg->u.s.icntxt);
+	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
+
+	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
+	if (sg_offset) {
 		struct sg_simple_element *sg;
 
-		if(sg_offset * 4 >= size) {
+		if (sg_offset * 4 >= size) {
 			rcode = -EFAULT;
 			goto cleanup;
 		}
 		// TODO 64bit fix
-		sg = (struct sg_simple_element*) (msg+sg_offset);
-		sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
+		sg = (struct sg_simple_element *)((&msg->u.head[0]) +
+						  sg_offset);
+		sg_count =
+		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
 		if (sg_count > SG_TABLESIZE) {
-			printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", c->name,sg_count);
-			kfree (reply);
+			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
+			       c->name, sg_count);
+			kfree(reply);
 			return -EINVAL;
 		}
 
-		for(i = 0; i < sg_count; i++) {
+		for (i = 0; i < sg_count; i++) {
 			int sg_size;
 
-			if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) {
-				printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",c->name,i,  sg[i].flag_count);
+			if (!(sg[i].flag_count & 0x10000000
+			      /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {
+				printk(KERN_DEBUG
+				       "%s:Bad SG element %d - not simple (%x)\n",
+				       c->name, i, sg[i].flag_count);
 				rcode = -EINVAL;
 				goto cleanup;
 			}
@@ -923,61 +950,78 @@
 			/* Allocate memory for the transfer */
 			p = kmalloc(sg_size, GFP_KERNEL);
 			if (!p) {
-				printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", c->name,sg_size,i,sg_count);
+				printk(KERN_DEBUG
+				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+				       c->name, sg_size, i, sg_count);
 				rcode = -ENOMEM;
 				goto cleanup;
 			}
-			sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
+			sg_list[sg_index++] = p;	// sglist indexed with input frame, not our internal frame.
 			/* Copy in the user's SG buffer if necessary */
-			if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) {
+			if (sg[i].
+			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
 				// TODO 64bit fix
-			        if (copy_from_user(p,(void __user *)sg[i].addr_bus, sg_size)) {
-					printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",c->name,i);
+				if (copy_from_user
+				    (p, (void __user *)sg[i].addr_bus,
+				     sg_size)) {
+					printk(KERN_DEBUG
+					       "%s: Could not copy SG buf %d FROM user\n",
+					       c->name, i);
 					rcode = -EFAULT;
 					goto cleanup;
 				}
 			}
 			//TODO 64bit fix
-			sg[i].addr_bus = (u32)virt_to_bus(p);
+			sg[i].addr_bus = virt_to_bus(p);
 		}
 	}
 
-	rcode = i2o_post_wait(c, msg, size, 60);
-	if(rcode)
+	rcode = i2o_msg_post_wait(c, m, 60);
+	if (rcode)
 		goto cleanup;
 
-	if(sg_offset) {
+	if (sg_offset) {
+		u32 msg[128];
 		/* Copy back the Scatter Gather buffers back to user space */
 		u32 j;
 		// TODO 64bit fix
-		struct sg_simple_element* sg;
+		struct sg_simple_element *sg;
 		int sg_size;
+		printk(KERN_INFO "sg_offset\n");
 
 		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, MSG_FRAME_SIZE*4);
+		memset(&msg, 0, MSG_FRAME_SIZE * 4);
 		// get user msg size in u32s
 		if (get_user(size, &user_msg[0])) {
 			rcode = -EFAULT;
 			goto cleanup;
 		}
-		size = size>>16;
+		size = size >> 16;
 		size *= 4;
 		/* Copy in the user's I2O command */
-		if (copy_from_user (msg, user_msg, size)) {
+		if (copy_from_user(msg, user_msg, size)) {
 			rcode = -EFAULT;
 			goto cleanup;
 		}
-		sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
+		sg_count =
+		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
 
-		 // TODO 64bit fix
-		sg = (struct sg_simple_element*)(msg + sg_offset);
+		// TODO 64bit fix
+		sg = (struct sg_simple_element *)(msg + sg_offset);
 		for (j = 0; j < sg_count; j++) {
 			/* Copy out the SG list to user's buffer if necessary */
-			if (!(sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) {
+			if (!
+			    (sg[j].
+			     flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {
 				sg_size = sg[j].flag_count & 0xffffff;
 				// TODO 64bit fix
-				if (copy_to_user((void __user *)sg[j].addr_bus,sg_list[j], sg_size)) {
-					printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",c->name, sg_list[j], sg[j].addr_bus);
+				if (copy_to_user
+				    ((void __user *)sg[j].addr_bus, sg_list[j],
+				     sg_size)) {
+					printk(KERN_WARNING
+					       "%s: Could not copy %p TO user %x\n",
+					       c->name, sg_list[j],
+					       sg[j].addr_bus);
 					rcode = -EFAULT;
 					goto cleanup;
 				}
@@ -986,37 +1030,109 @@
 	}
 
 	/* Copy back the reply to user space */
-        if (reply_size) {
+	if (reply_size) {
 		// we wrote our own values for context - now restore the user supplied ones
-		if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) {
-			printk(KERN_WARNING"%s: Could not copy message context FROM user\n",c->name);
+		printk(KERN_INFO "reply_size\n");
+		if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {
+			printk(KERN_WARNING
+			       "%s: Could not copy message context FROM user\n",
+			       c->name);
 			rcode = -EFAULT;
 		}
-		if(copy_to_user(user_reply, reply, reply_size)) {
-			printk(KERN_WARNING"%s: Could not copy reply TO user\n",c->name);
+		if (copy_to_user(user_reply, reply, reply_size)) {
+			printk(KERN_WARNING
+			       "%s: Could not copy reply TO user\n", c->name);
 			rcode = -EFAULT;
 		}
 	}
 
-cleanup:
+      cleanup:
 	kfree(reply);
-	i2o_unlock_controller(c);
 	return rcode;
 }
+#endif
+
+/*
+ * IOCTL Handler
+ */
+static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
+			 unsigned long arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case I2OGETIOPS:
+		ret = i2o_cfg_getiops(arg);
+		break;
+
+	case I2OHRTGET:
+		ret = i2o_cfg_gethrt(arg);
+		break;
+
+	case I2OLCTGET:
+		ret = i2o_cfg_getlct(arg);
+		break;
+
+	case I2OPARMSET:
+		ret = i2o_cfg_parms(arg, I2OPARMSET);
+		break;
+
+	case I2OPARMGET:
+		ret = i2o_cfg_parms(arg, I2OPARMGET);
+		break;
+
+	case I2OSWDL:
+		ret = i2o_cfg_swdl(arg);
+		break;
+
+	case I2OSWUL:
+		ret = i2o_cfg_swul(arg);
+		break;
+
+	case I2OSWDEL:
+		ret = i2o_cfg_swdel(arg);
+		break;
+
+	case I2OVALIDATE:
+		ret = i2o_cfg_validate(arg);
+		break;
+
+	case I2OEVTREG:
+		ret = i2o_cfg_evt_reg(arg, fp);
+		break;
+
+	case I2OEVTGET:
+		ret = i2o_cfg_evt_get(arg, fp);
+		break;
+
+#if BITS_PER_LONG != 64
+	case I2OPASSTHRU:
+		ret = i2o_cfg_passthru(arg);
+		break;
+#endif
+
+	default:
+		pr_debug("i2o_config: unknown ioctl called!\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
 
 static int cfg_open(struct inode *inode, struct file *file)
 {
-	struct i2o_cfg_info *tmp = 
-		(struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), GFP_KERNEL);
+	struct i2o_cfg_info *tmp =
+	    (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info),
+					   GFP_KERNEL);
 	unsigned long flags;
 
-	if(!tmp)
+	if (!tmp)
 		return -ENOMEM;
 
-	file->private_data = (void*)(i2o_cfg_info_id++);
+	file->private_data = (void *)(i2o_cfg_info_id++);
 	tmp->fp = file;
 	tmp->fasync = NULL;
-	tmp->q_id = (u32)file->private_data;
+	tmp->q_id = (ulong) file->private_data;
 	tmp->q_len = 0;
 	tmp->q_in = 0;
 	tmp->q_out = 0;
@@ -1026,13 +1142,28 @@
 	spin_lock_irqsave(&i2o_config_lock, flags);
 	open_files = tmp;
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
-	
+
 	return 0;
 }
 
+static int cfg_fasync(int fd, struct file *fp, int on)
+{
+	ulong id = (ulong) fp->private_data;
+	struct i2o_cfg_info *p;
+
+	for (p = open_files; p; p = p->next)
+		if (p->q_id == id)
+			break;
+
+	if (!p)
+		return -EBADF;
+
+	return fasync_helper(fd, fp, on, &p->fasync);
+}
+
 static int cfg_release(struct inode *inode, struct file *file)
 {
-	u32 id = (u32)file->private_data;
+	ulong id = (ulong) file->private_data;
 	struct i2o_cfg_info *p1, *p2;
 	unsigned long flags;
 
@@ -1040,14 +1171,12 @@
 	p1 = p2 = NULL;
 
 	spin_lock_irqsave(&i2o_config_lock, flags);
-	for(p1 = open_files; p1; )
-	{
-		if(p1->q_id == id)
-		{
+	for (p1 = open_files; p1;) {
+		if (p1->q_id == id) {
 
-			if(p1->fasync)
+			if (p1->fasync)
 				cfg_fasync(-1, file, 0);
-			if(p2)
+			if (p2)
 				p2->next = p1->next;
 			else
 				open_files = p1->next;
@@ -1064,83 +1193,55 @@
 	return 0;
 }
 
-static int cfg_fasync(int fd, struct file *fp, int on)
-{
-	u32 id = (u32)fp->private_data;
-	struct i2o_cfg_info *p;
-
-	for(p = open_files; p; p = p->next)
-		if(p->q_id == id)
-			break;
-
-	if(!p)
-		return -EBADF;
-
-	return fasync_helper(fd, fp, on, &p->fasync);
-}
-
-static struct file_operations config_fops =
-{
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= cfg_read,
-	.write		= cfg_write,
-	.ioctl		= cfg_ioctl,
-	.open		= cfg_open,
-	.release	= cfg_release,
-	.fasync		= cfg_fasync,
+static struct file_operations config_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.ioctl = i2o_cfg_ioctl,
+	.open = cfg_open,
+	.release = cfg_release,
+	.fasync = cfg_fasync,
 };
 
 static struct miscdevice i2o_miscdev = {
 	I2O_MINOR,
 	"i2octl",
 	&config_fops
-};	
+};
 
 static int __init i2o_config_init(void)
 {
 	printk(KERN_INFO "I2O configuration manager v 0.04.\n");
 	printk(KERN_INFO "  (C) Copyright 1999 Red Hat Software\n");
-	
-	if((page_buf = kmalloc(4096, GFP_KERNEL))==NULL)
-	{
-		printk(KERN_ERR "i2o_config: no memory for page buffer.\n");
-		return -ENOBUFS;
-	}
-	if(misc_register(&i2o_miscdev) < 0)
-	{
+
+	if (misc_register(&i2o_miscdev) < 0) {
 		printk(KERN_ERR "i2o_config: can't register device.\n");
-		kfree(page_buf);
 		return -EBUSY;
 	}
 	/*
-	 *	Install our handler
+	 *      Install our handler
 	 */
-	if(i2o_install_handler(&cfg_handler)<0)
-	{
-		kfree(page_buf);
+	if (i2o_driver_register(&i2o_config_driver)) {
 		printk(KERN_ERR "i2o_config: handler register failed.\n");
 		misc_deregister(&i2o_miscdev);
 		return -EBUSY;
 	}
-	/*
-	 *	The low 16bits of the transaction context must match this
-	 *	for everything we post. Otherwise someone else gets our mail
-	 */
-	i2o_cfg_context = cfg_handler.context;
+#if BITS_PER_LONG ==64
+	register_ioctl32_conversion(I2OPASSTHRU32, i2o_cfg_passthru32);
+	register_ioctl32_conversion(I2OGETIOPS, (void *)sys_ioctl);
+#endif
 	return 0;
 }
 
 static void i2o_config_exit(void)
 {
+#if BITS_PER_LONG ==64
+	unregister_ioctl32_conversion(I2OPASSTHRU32);
+	unregister_ioctl32_conversion(I2OGETIOPS);
+#endif
 	misc_deregister(&i2o_miscdev);
-	
-	if(page_buf)
-		kfree(page_buf);
-	if(i2o_cfg_context != -1)
-		i2o_remove_handler(&cfg_handler);
+	i2o_driver_unregister(&i2o_config_driver);
 }
- 
+
 MODULE_AUTHOR("Red Hat Software");
 MODULE_DESCRIPTION("I2O Configuration");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
--- a/drivers/message/i2o/i2o_proc.c	2004-07-12 01:01:06 -07:00
+++ b/drivers/message/i2o/i2o_proc.c	2004-08-24 11:29:24 -07:00
@@ -1,39 +1,33 @@
 /*
- *   procfs handler for Linux I2O subsystem
+ *	procfs handler for Linux I2O subsystem
  *
- *   (c) Copyright 1999 Deepak Saxena
- *   
- *   Originally written by Deepak Saxena(deepak@plexity.net)
- *
- *   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 of the License, or (at your option) any later version.
- *
- *   This is an initial test release. The code is based on the design
- *   of the ide procfs system (drivers/block/ide-proc.c). Some code
- *   taken from i2o-core module by Alan Cox.
- *
- *   DISCLAIMER: This code is still under development/test and may cause
- *   your system to behave unpredictably.  Use at your own discretion.
- *
- *   LAN entries by Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI),
- *		    Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI)
- *   University of Helsinki, Department of Computer Science
- */
-
-/*
- * set tabstop=3
- */
-
-/*
- * TODO List
+ *	(c) Copyright 1999	Deepak Saxena
+ *
+ *	Originally written by Deepak Saxena(deepak@plexity.net)
  *
- * - Add support for any version 2.0 spec changes once 2.0 IRTOS is
- *   is available to test with
- * - Clean up code to use official structure definitions 
+ *	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 of the License, or (at your
+ *	option) any later version.
+ *
+ *	This is an initial test release. The code is based on the design of the
+ *	ide procfs system (drivers/block/ide-proc.c). Some code taken from
+ *	i2o-core module by Alan Cox.
+ *
+ *	DISCLAIMER: This code is still under development/test and may cause
+ *	your system to behave unpredictably.  Use at your own discretion.
+ *
+ *
+ *	Fixes/additions:
+ *		Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI),
+ *		Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI)
+ *		University of Helsinki, Department of Computer Science
+ *			LAN entries
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *			Changes for new I2O API
  */
 
+#define I2O_MAX_MODULES 4
 // FIXME!
 #define FMT_U64_HEX "0x%08x%08x"
 #define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64))
@@ -54,188 +48,198 @@
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
-#include "i2o_lan.h"
-
-/*
- * Structure used to define /proc entries
- */
-typedef struct _i2o_proc_entry_t
-{
-	char *name;			/* entry name */
-	mode_t mode;			/* mode */
-	read_proc_t *read_proc;		/* read func */
-	write_proc_t *write_proc;	/* write func */
-	struct file_operations *fops_proc;	/* file operations func */
+/* Structure used to define /proc entries */
+typedef struct _i2o_proc_entry_t {
+	char *name;		/* entry name */
+	mode_t mode;		/* mode */
+	struct file_operations *fops;	/* open function */
 } i2o_proc_entry;
 
-// #define DRIVERDEBUG
-
-static int i2o_seq_show_lct(struct seq_file *, void *);
-static int i2o_seq_show_hrt(struct seq_file *, void *);
-static int i2o_seq_show_status(struct seq_file *, void *);
-
-static int i2o_proc_read_hw(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_ddm_table(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_driver_store(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_drivers_stored(char *, char **, off_t, int, int *, void *);
-
-static int i2o_proc_read_groups(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_phys_device(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_claimed(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_users(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_priv_msgs(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_authorized_users(char *, char **, off_t, int, int *, void *);
-
-static int i2o_proc_read_dev_name(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_dev_identity(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_ddm_identity(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_uinfo(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_sgl_limits(char *, char **, off_t, int, int *, void *);
-
-static int i2o_proc_read_sensors(char *, char **, off_t, int, int *, void *);
-
-static int print_serial_number(char *, int, u8 *, int);
-
-static int i2o_proc_create_entries(void *, i2o_proc_entry *,
-				   struct proc_dir_entry *);
-static void i2o_proc_remove_entries(i2o_proc_entry *, struct proc_dir_entry *);
-static int i2o_proc_add_controller(struct i2o_controller *, 
-				   struct proc_dir_entry * );
-static void i2o_proc_remove_controller(struct i2o_controller *, 
-				       struct proc_dir_entry * );
-static void i2o_proc_add_device(struct i2o_device *, struct proc_dir_entry *);
-static void i2o_proc_remove_device(struct i2o_device *);
-static int create_i2o_procfs(void);
-static int destroy_i2o_procfs(void);
-static void i2o_proc_new_dev(struct i2o_controller *, struct i2o_device *);
-static void i2o_proc_dev_del(struct i2o_controller *, struct i2o_device *);
-
-static int i2o_proc_read_lan_dev_info(char *, char **, off_t, int, int *,
-				      void *);
-static int i2o_proc_read_lan_mac_addr(char *, char **, off_t, int, int *,
-				      void *);
-static int i2o_proc_read_lan_mcast_addr(char *, char **, off_t, int, int *,
-					void *);
-static int i2o_proc_read_lan_batch_control(char *, char **, off_t, int, int *,
-					   void *);
-static int i2o_proc_read_lan_operation(char *, char **, off_t, int, int *,
-				       void *);
-static int i2o_proc_read_lan_media_operation(char *, char **, off_t, int,
-					     int *, void *);
-static int i2o_proc_read_lan_alt_addr(char *, char **, off_t, int, int *,
-				      void *);
-static int i2o_proc_read_lan_tx_info(char *, char **, off_t, int, int *,
-				     void *);
-static int i2o_proc_read_lan_rx_info(char *, char **, off_t, int, int *,
-				     void *);
-static int i2o_proc_read_lan_hist_stats(char *, char **, off_t, int, int *,
-					void *);
-static int i2o_proc_read_lan_eth_stats(char *, char **, off_t, int,
-				       int *, void *);
-static int i2o_proc_read_lan_tr_stats(char *, char **, off_t, int, int *,
-				      void *);
-static int i2o_proc_read_lan_fddi_stats(char *, char **, off_t, int, int *,
-					void *);
-
+/* global I2O /proc/i2o entry */
 static struct proc_dir_entry *i2o_proc_dir_root;
 
-/*
- * I2O OSM descriptor
- */
-static struct i2o_handler i2o_proc_handler =
-{
-	NULL,
-	i2o_proc_new_dev,
-	i2o_proc_dev_del,
-	NULL,
-	"I2O procfs Layer",
-	0,
-	0xffffffff	// All classes
+/* proc OSM driver struct */
+static struct i2o_driver i2o_proc_driver = {
+	.name = "proc-osm",
 };
 
-static int i2o_seq_open_hrt(struct inode *inode, struct file *file)
+static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len)
 {
-	return single_open(file, i2o_seq_show_hrt, PDE(inode)->data);
-};
+	int i;
 
-struct file_operations i2o_seq_fops_hrt = {
-	.open	= i2o_seq_open_hrt,
-	.read	= seq_read,
-	.llseek	= seq_lseek,
-	.release = single_release
-};
+	/* 19990419 -sralston
+	 *      The I2O v1.5 (and v2.0 so far) "official specification"
+	 *      got serial numbers WRONG!
+	 *      Apparently, and despite what Section 3.4.4 says and
+	 *      Figure 3-35 shows (pg 3-39 in the pdf doc),
+	 *      the convention / consensus seems to be:
+	 *        + First byte is SNFormat
+	 *        + Second byte is SNLen (but only if SNFormat==7 (?))
+	 *        + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format
+	 */
+	switch (serialno[0]) {
+	case I2O_SNFORMAT_BINARY:	/* Binary */
+		seq_printf(seq, "0x");
+		for (i = 0; i < serialno[1]; i++) {
+			seq_printf(seq, "%02X", serialno[2 + i]);
+		}
+		break;
 
-static int i2o_seq_open_lct(struct inode *inode, struct file *file)
-{
-	return single_open(file, i2o_seq_show_lct, PDE(inode)->data);
-};
+	case I2O_SNFORMAT_ASCII:	/* ASCII */
+		if (serialno[1] < ' ') {	/* printable or SNLen? */
+			/* sanity */
+			max_len =
+			    (max_len < serialno[1]) ? max_len : serialno[1];
+			serialno[1 + max_len] = '\0';
+
+			/* just print it */
+			seq_printf(seq, "%s", &serialno[2]);
+		} else {
+			/* print chars for specified length */
+			for (i = 0; i < serialno[1]; i++) {
+				seq_printf(seq, "%c", serialno[2 + i]);
+			}
+		}
+		break;
 
-struct file_operations i2o_seq_fops_lct = {
-	.open	= i2o_seq_open_lct,
-	.read	= seq_read,
-	.llseek	= seq_lseek,
-	.release = single_release
-};
+	case I2O_SNFORMAT_UNICODE:	/* UNICODE */
+		seq_printf(seq, "UNICODE Format.  Can't Display\n");
+		break;
 
-static int i2o_seq_open_status(struct inode *inode, struct file *file)
-{
-	return single_open(file, i2o_seq_show_status, PDE(inode)->data);
-};
+	case I2O_SNFORMAT_LAN48_MAC:	/* LAN-48 MAC Address */
+		seq_printf(seq,
+			   "LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X",
+			   serialno[2], serialno[3],
+			   serialno[4], serialno[5], serialno[6], serialno[7]);
+		break;
 
-struct file_operations i2o_seq_fops_status = {
-	.open	= i2o_seq_open_status,
-	.read	= seq_read,
-	.llseek	= seq_lseek,
-	.release = single_release
-};
+	case I2O_SNFORMAT_WAN:	/* WAN MAC Address */
+		/* FIXME: Figure out what a WAN access address looks like?? */
+		seq_printf(seq, "WAN Access Address");
+		break;
 
-/*
- * IOP specific entries...write field just in case someone 
- * ever wants one.
- */
-static i2o_proc_entry generic_iop_entries[] = 
-{
-	{"hrt", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_hrt},
-	{"lct", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_lct},
-	{"status", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_status},
-	{"hw", S_IFREG|S_IRUGO, i2o_proc_read_hw, NULL, NULL},
-	{"ddm_table", S_IFREG|S_IRUGO, i2o_proc_read_ddm_table, NULL, NULL},
-	{"driver_store", S_IFREG|S_IRUGO, i2o_proc_read_driver_store, NULL, NULL},
-	{"drivers_stored", S_IFREG|S_IRUGO, i2o_proc_read_drivers_stored, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
+/* plus new in v2.0 */
+	case I2O_SNFORMAT_LAN64_MAC:	/* LAN-64 MAC Address */
+		/* FIXME: Figure out what a LAN-64 address really looks like?? */
+		seq_printf(seq,
+			   "LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X",
+			   serialno[8], serialno[9],
+			   serialno[2], serialno[3],
+			   serialno[4], serialno[5], serialno[6], serialno[7]);
+		break;
+
+	case I2O_SNFORMAT_DDM:	/* I2O DDM */
+		seq_printf(seq,
+			   "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh",
+			   *(u16 *) & serialno[2],
+			   *(u16 *) & serialno[4], *(u16 *) & serialno[6]);
+		break;
+
+	case I2O_SNFORMAT_IEEE_REG64:	/* IEEE Registered (64-bit) */
+	case I2O_SNFORMAT_IEEE_REG128:	/* IEEE Registered (128-bit) */
+		/* FIXME: Figure if this is even close?? */
+		seq_printf(seq,
+			   "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n",
+			   *(u32 *) & serialno[2],
+			   *(u32 *) & serialno[6],
+			   *(u32 *) & serialno[10], *(u32 *) & serialno[14]);
+		break;
 
-/*
- * Device specific entries
- */
-static i2o_proc_entry generic_dev_entries[] = 
-{
-	{"groups", S_IFREG|S_IRUGO, i2o_proc_read_groups, NULL, NULL},
-	{"phys_dev", S_IFREG|S_IRUGO, i2o_proc_read_phys_device, NULL, NULL},
-	{"claimed", S_IFREG|S_IRUGO, i2o_proc_read_claimed, NULL, NULL},
-	{"users", S_IFREG|S_IRUGO, i2o_proc_read_users, NULL, NULL},
-	{"priv_msgs", S_IFREG|S_IRUGO, i2o_proc_read_priv_msgs, NULL, NULL},
-	{"authorized_users", S_IFREG|S_IRUGO, i2o_proc_read_authorized_users, NULL, NULL},
-	{"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev_identity, NULL, NULL},
-	{"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm_identity, NULL, NULL},
-	{"user_info", S_IFREG|S_IRUGO, i2o_proc_read_uinfo, NULL, NULL},
-	{"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL, NULL},
-	{"sensors", S_IFREG|S_IRUGO, i2o_proc_read_sensors, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
+	case I2O_SNFORMAT_UNKNOWN:	/* Unknown 0    */
+	case I2O_SNFORMAT_UNKNOWN2:	/* Unknown 0xff */
+	default:
+		seq_printf(seq, "Unknown data format (0x%02x)", serialno[0]);
+		break;
+	}
 
-/*
- *  Storage unit specific entries (SCSI Periph, BS) with device names
+	return 0;
+}
+
+/**
+ *	i2o_get_class_name - 	do i2o class name lookup
+ *	@class: class number
+ *
+ *	Return a descriptive string for an i2o class
  */
-static i2o_proc_entry rbs_dev_entries[] = 
+static const char *i2o_get_class_name(int class)
 {
-	{"dev_name", S_IFREG|S_IRUGO, i2o_proc_read_dev_name, NULL, NULL},
-	{NULL, 0, NULL, NULL}
-};
+	int idx = 16;
+	static char *i2o_class_name[] = {
+		"Executive",
+		"Device Driver Module",
+		"Block Device",
+		"Tape Device",
+		"LAN Interface",
+		"WAN Interface",
+		"Fibre Channel Port",
+		"Fibre Channel Device",
+		"SCSI Device",
+		"ATE Port",
+		"ATE Device",
+		"Floppy Controller",
+		"Floppy Device",
+		"Secondary Bus Port",
+		"Peer Transport Agent",
+		"Peer Transport",
+		"Unknown"
+	};
+
+	switch (class & 0xfff) {
+	case I2O_CLASS_EXECUTIVE:
+		idx = 0;
+		break;
+	case I2O_CLASS_DDM:
+		idx = 1;
+		break;
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+		idx = 2;
+		break;
+	case I2O_CLASS_SEQUENTIAL_STORAGE:
+		idx = 3;
+		break;
+	case I2O_CLASS_LAN:
+		idx = 4;
+		break;
+	case I2O_CLASS_WAN:
+		idx = 5;
+		break;
+	case I2O_CLASS_FIBRE_CHANNEL_PORT:
+		idx = 6;
+		break;
+	case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
+		idx = 7;
+		break;
+	case I2O_CLASS_SCSI_PERIPHERAL:
+		idx = 8;
+		break;
+	case I2O_CLASS_ATE_PORT:
+		idx = 9;
+		break;
+	case I2O_CLASS_ATE_PERIPHERAL:
+		idx = 10;
+		break;
+	case I2O_CLASS_FLOPPY_CONTROLLER:
+		idx = 11;
+		break;
+	case I2O_CLASS_FLOPPY_DEVICE:
+		idx = 12;
+		break;
+	case I2O_CLASS_BUS_ADAPTER_PORT:
+		idx = 13;
+		break;
+	case I2O_CLASS_PEER_TRANSPORT_AGENT:
+		idx = 14;
+		break;
+	case I2O_CLASS_PEER_TRANSPORT:
+		idx = 15;
+		break;
+	}
+
+	return i2o_class_name[idx];
+}
 
 #define SCSI_TABLE_SIZE	13
-static char *scsi_devices[] = 
-{
+static char *scsi_devices[] = {
 	"Direct-Access Read/Write",
 	"Sequential-Access Storage",
 	"Printer",
@@ -251,307 +255,267 @@
 	"Array Controller Device"
 };
 
-/* private */
-
-/*
- * Generic LAN specific entries
- * 
- * Should groups with r/w entries have their own subdirectory?
- *
- */
-static i2o_proc_entry lan_entries[] = 
-{
-	{"lan_dev_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_dev_info, NULL, NULL},
-	{"lan_mac_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_mac_addr, NULL, NULL},
-	{"lan_mcast_addr", S_IFREG|S_IRUGO|S_IWUSR,
-	 i2o_proc_read_lan_mcast_addr, NULL, NULL},
-	{"lan_batch_ctrl", S_IFREG|S_IRUGO|S_IWUSR,
-	 i2o_proc_read_lan_batch_control, NULL, NULL},
-	{"lan_operation", S_IFREG|S_IRUGO, i2o_proc_read_lan_operation, NULL, NULL},
-	{"lan_media_operation", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_media_operation, NULL, NULL},
-	{"lan_alt_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_alt_addr, NULL, NULL},
-	{"lan_tx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_tx_info, NULL, NULL},
-	{"lan_rx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_rx_info, NULL, NULL},
-
-	{"lan_hist_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
-
-/*
- * Port specific LAN entries
- * 
- */
-static i2o_proc_entry lan_eth_entries[] = 
-{
-	{"lan_eth_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
-
-static i2o_proc_entry lan_tr_entries[] = 
-{
-	{"lan_tr_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_tr_stats, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
-
-static i2o_proc_entry lan_fddi_entries[] = 
-{
-	{"lan_fddi_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_fddi_stats, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
-
-
-static char *chtostr(u8 *chars, int n)
+static char *chtostr(u8 * chars, int n)
 {
 	char tmp[256];
 	tmp[0] = 0;
-        return strncat(tmp, (char *)chars, n);
+	return strncat(tmp, (char *)chars, n);
 }
 
-static int i2o_report_query_status(char *buf, int block_status, char *group)
+static int i2o_report_query_status(struct seq_file *seq, int block_status,
+				   char *group)
 {
-	switch (block_status)
-	{
+	switch (block_status) {
 	case -ETIMEDOUT:
-		return sprintf(buf, "Timeout reading group %s.\n",group);
+		return seq_printf(seq, "Timeout reading group %s.\n", group);
 	case -ENOMEM:
-		return sprintf(buf, "No free memory to read the table.\n");
+		return seq_printf(seq, "No free memory to read the table.\n");
 	case -I2O_PARAMS_STATUS_INVALID_GROUP_ID:
-		return sprintf(buf, "Group %s not supported.\n", group);
+		return seq_printf(seq, "Group %s not supported.\n", group);
 	default:
-		return sprintf(buf, "Error reading group %s. BlockStatus 0x%02X\n",
-			       group, -block_status);
+		return seq_printf(seq,
+				  "Error reading group %s. BlockStatus 0x%02X\n",
+				  group, -block_status);
 	}
 }
 
-static char* bus_strings[] = 
-{ 
-	"Local Bus", 
-	"ISA", 
-	"EISA", 
-	"MCA", 
+static char *bus_strings[] = {
+	"Local Bus",
+	"ISA",
+	"EISA",
+	"MCA",
 	"PCI",
-	"PCMCIA", 
-	"NUBUS", 
+	"PCMCIA",
+	"NUBUS",
 	"CARDBUS"
 };
 
-static spinlock_t i2o_proc_lock = SPIN_LOCK_UNLOCKED;
-
 int i2o_seq_show_hrt(struct seq_file *seq, void *v)
 {
 	struct i2o_controller *c = (struct i2o_controller *)seq->private;
-	i2o_hrt *hrt = (i2o_hrt *)c->hrt;
+	i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt;
 	u32 bus;
 	int i;
 
-	if(hrt->hrt_version)
-	{
-		seq_printf(seq, "HRT table for controller is too new a version.\n");
+	if (hrt->hrt_version) {
+		seq_printf(seq,
+			   "HRT table for controller is too new a version.\n");
 		return 0;
 	}
 
 	seq_printf(seq, "HRT has %d entries of %d bytes each.\n",
-		       hrt->num_entries, hrt->entry_len << 2);
+		   hrt->num_entries, hrt->entry_len << 2);
 
-	for(i = 0; i < hrt->num_entries; i++)
-	{
+	for (i = 0; i < hrt->num_entries; i++) {
 		seq_printf(seq, "Entry %d:\n", i);
 		seq_printf(seq, "   Adapter ID: %0#10x\n",
-					hrt->hrt_entry[i].adapter_id);
+			   hrt->hrt_entry[i].adapter_id);
 		seq_printf(seq, "   Controlling tid: %0#6x\n",
-					hrt->hrt_entry[i].parent_tid);
+			   hrt->hrt_entry[i].parent_tid);
 
-		if(hrt->hrt_entry[i].bus_type != 0x80)
-		{
+		if (hrt->hrt_entry[i].bus_type != 0x80) {
 			bus = hrt->hrt_entry[i].bus_type;
-			seq_printf(seq, "   %s Information\n", bus_strings[bus]);
+			seq_printf(seq, "   %s Information\n",
+				   bus_strings[bus]);
+
+			switch (bus) {
+			case I2O_BUS_LOCAL:
+				seq_printf(seq, "     IOBase: %0#6x,",
+					   hrt->hrt_entry[i].bus.local_bus.
+					   LbBaseIOPort);
+				seq_printf(seq, " MemoryBase: %0#10x\n",
+					   hrt->hrt_entry[i].bus.local_bus.
+					   LbBaseMemoryAddress);
+				break;
 
-			switch(bus)
-			{
-				case I2O_BUS_LOCAL:
-					seq_printf(seq, "     IOBase: %0#6x,",
-								hrt->hrt_entry[i].bus.local_bus.LbBaseIOPort);
-					seq_printf(seq, " MemoryBase: %0#10x\n",
-								hrt->hrt_entry[i].bus.local_bus.LbBaseMemoryAddress);
-					break;
-
-				case I2O_BUS_ISA:
-					seq_printf(seq, "     IOBase: %0#6x,",
-								hrt->hrt_entry[i].bus.isa_bus.IsaBaseIOPort);
-					seq_printf(seq, " MemoryBase: %0#10x,",
-								hrt->hrt_entry[i].bus.isa_bus.IsaBaseMemoryAddress);
-					seq_printf(seq, " CSN: %0#4x,",
-								hrt->hrt_entry[i].bus.isa_bus.CSN);
-					break;
-
-				case I2O_BUS_EISA:
-					seq_printf(seq, "     IOBase: %0#6x,",
-								hrt->hrt_entry[i].bus.eisa_bus.EisaBaseIOPort);
-					seq_printf(seq, " MemoryBase: %0#10x,",
-								hrt->hrt_entry[i].bus.eisa_bus.EisaBaseMemoryAddress);
-					seq_printf(seq, " Slot: %0#4x,",
-								hrt->hrt_entry[i].bus.eisa_bus.EisaSlotNumber);
-					break;
-			 
-				case I2O_BUS_MCA:
-					seq_printf(seq, "     IOBase: %0#6x,",
-								hrt->hrt_entry[i].bus.mca_bus.McaBaseIOPort);
-					seq_printf(seq, " MemoryBase: %0#10x,",
-								hrt->hrt_entry[i].bus.mca_bus.McaBaseMemoryAddress);
-					seq_printf(seq, " Slot: %0#4x,",
-								hrt->hrt_entry[i].bus.mca_bus.McaSlotNumber);
-					break;
-
-				case I2O_BUS_PCI:
-					seq_printf(seq, "     Bus: %0#4x",
-								hrt->hrt_entry[i].bus.pci_bus.PciBusNumber);
-					seq_printf(seq, " Dev: %0#4x",
-								hrt->hrt_entry[i].bus.pci_bus.PciDeviceNumber);
-					seq_printf(seq, " Func: %0#4x",
-								hrt->hrt_entry[i].bus.pci_bus.PciFunctionNumber);
-					seq_printf(seq, " Vendor: %0#6x",
-								hrt->hrt_entry[i].bus.pci_bus.PciVendorID);
-					seq_printf(seq, " Device: %0#6x\n",
-								hrt->hrt_entry[i].bus.pci_bus.PciDeviceID);
-					break;
+			case I2O_BUS_ISA:
+				seq_printf(seq, "     IOBase: %0#6x,",
+					   hrt->hrt_entry[i].bus.isa_bus.
+					   IsaBaseIOPort);
+				seq_printf(seq, " MemoryBase: %0#10x,",
+					   hrt->hrt_entry[i].bus.isa_bus.
+					   IsaBaseMemoryAddress);
+				seq_printf(seq, " CSN: %0#4x,",
+					   hrt->hrt_entry[i].bus.isa_bus.CSN);
+				break;
+
+			case I2O_BUS_EISA:
+				seq_printf(seq, "     IOBase: %0#6x,",
+					   hrt->hrt_entry[i].bus.eisa_bus.
+					   EisaBaseIOPort);
+				seq_printf(seq, " MemoryBase: %0#10x,",
+					   hrt->hrt_entry[i].bus.eisa_bus.
+					   EisaBaseMemoryAddress);
+				seq_printf(seq, " Slot: %0#4x,",
+					   hrt->hrt_entry[i].bus.eisa_bus.
+					   EisaSlotNumber);
+				break;
+
+			case I2O_BUS_MCA:
+				seq_printf(seq, "     IOBase: %0#6x,",
+					   hrt->hrt_entry[i].bus.mca_bus.
+					   McaBaseIOPort);
+				seq_printf(seq, " MemoryBase: %0#10x,",
+					   hrt->hrt_entry[i].bus.mca_bus.
+					   McaBaseMemoryAddress);
+				seq_printf(seq, " Slot: %0#4x,",
+					   hrt->hrt_entry[i].bus.mca_bus.
+					   McaSlotNumber);
+				break;
+
+			case I2O_BUS_PCI:
+				seq_printf(seq, "     Bus: %0#4x",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciBusNumber);
+				seq_printf(seq, " Dev: %0#4x",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciDeviceNumber);
+				seq_printf(seq, " Func: %0#4x",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciFunctionNumber);
+				seq_printf(seq, " Vendor: %0#6x",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciVendorID);
+				seq_printf(seq, " Device: %0#6x\n",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciDeviceID);
+				break;
 
-				default:
-					seq_printf(seq, "      Unsupported Bus Type\n");
+			default:
+				seq_printf(seq, "      Unsupported Bus Type\n");
 			}
-		}
-		else
+		} else
 			seq_printf(seq, "   Unknown Bus Type\n");
 	}
-	
+
 	return 0;
 }
 
 int i2o_seq_show_lct(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)seq->private;
-	i2o_lct *lct = (i2o_lct *)c->lct;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
+	i2o_lct *lct = (i2o_lct *) c->lct;
 	int entries;
 	int i;
 
 #define BUS_TABLE_SIZE 3
-	static char *bus_ports[] =
-	{
+	static char *bus_ports[] = {
 		"Generic Bus",
 		"SCSI Bus",
 		"Fibre Channel Bus"
 	};
 
-	entries = (lct->table_size - 3)/9;
+	entries = (lct->table_size - 3) / 9;
 
 	seq_printf(seq, "LCT contains %d %s\n", entries,
-						entries == 1 ? "entry" : "entries");
-	if(lct->boot_tid)	
+		   entries == 1 ? "entry" : "entries");
+	if (lct->boot_tid)
 		seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid);
 
 	seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind);
 
-	for(i = 0; i < entries; i++)
-	{
+	for (i = 0; i < entries; i++) {
 		seq_printf(seq, "Entry %d\n", i);
-		seq_printf(seq, "  Class, SubClass  : %s", i2o_get_class_name(lct->lct_entry[i].class_id));
-	
+		seq_printf(seq, "  Class, SubClass  : %s",
+			   i2o_get_class_name(lct->lct_entry[i].class_id));
+
 		/*
-		 *	Classes which we'll print subclass info for
+		 *      Classes which we'll print subclass info for
 		 */
-		switch(lct->lct_entry[i].class_id & 0xFFF)
-		{
-			case I2O_CLASS_RANDOM_BLOCK_STORAGE:
-				switch(lct->lct_entry[i].sub_class)
-				{
-					case 0x00:
-						seq_printf(seq, ", Direct-Access Read/Write");
-						break;
-
-					case 0x04:
-						seq_printf(seq, ", WORM Drive");
-						break;
-	
-					case 0x05:
-						seq_printf(seq, ", CD-ROM Drive");
-						break;
-
-					case 0x07:
-						seq_printf(seq, ", Optical Memory Device");
-						break;
-
-					default:
-						seq_printf(seq, ", Unknown (0x%02x)",
-							       lct->lct_entry[i].sub_class);
-						break;
-				}
-				break;
-
-			case I2O_CLASS_LAN:
-				switch(lct->lct_entry[i].sub_class & 0xFF)
-				{
-					case 0x30:
-						seq_printf(seq, ", Ethernet");
-						break;
-
-					case 0x40:
-						seq_printf(seq, ", 100base VG");
-						break;
-
-					case 0x50:
-						seq_printf(seq, ", IEEE 802.5/Token-Ring");
-						break;
-
-					case 0x60:
-						seq_printf(seq, ", ANSI X3T9.5 FDDI");
-						break;
-		
-					case 0x70:
-						seq_printf(seq, ", Fibre Channel");
-						break;
-
-					default:
-						seq_printf(seq, ", Unknown Sub-Class (0x%02x)",
-							       lct->lct_entry[i].sub_class & 0xFF);
-						break;
-				}
-				break;
-
-			case I2O_CLASS_SCSI_PERIPHERAL:
-				if(lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE)
-					seq_printf(seq, ", %s",
-								scsi_devices[lct->lct_entry[i].sub_class]);
-				else
-					seq_printf(seq, ", Unknown Device Type");
-				break;
-
-			case I2O_CLASS_BUS_ADAPTER_PORT:
-				if(lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
-					seq_printf(seq, ", %s",
-								bus_ports[lct->lct_entry[i].sub_class]);
-				else
-					seq_printf(seq, ", Unknown Bus Type");
+		switch (lct->lct_entry[i].class_id & 0xFFF) {
+		case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+			switch (lct->lct_entry[i].sub_class) {
+			case 0x00:
+				seq_printf(seq, ", Direct-Access Read/Write");
+				break;
+
+			case 0x04:
+				seq_printf(seq, ", WORM Drive");
+				break;
+
+			case 0x05:
+				seq_printf(seq, ", CD-ROM Drive");
+				break;
+
+			case 0x07:
+				seq_printf(seq, ", Optical Memory Device");
+				break;
+
+			default:
+				seq_printf(seq, ", Unknown (0x%02x)",
+					   lct->lct_entry[i].sub_class);
+				break;
+			}
+			break;
+
+		case I2O_CLASS_LAN:
+			switch (lct->lct_entry[i].sub_class & 0xFF) {
+			case 0x30:
+				seq_printf(seq, ", Ethernet");
+				break;
+
+			case 0x40:
+				seq_printf(seq, ", 100base VG");
+				break;
+
+			case 0x50:
+				seq_printf(seq, ", IEEE 802.5/Token-Ring");
+				break;
+
+			case 0x60:
+				seq_printf(seq, ", ANSI X3T9.5 FDDI");
 				break;
+
+			case 0x70:
+				seq_printf(seq, ", Fibre Channel");
+				break;
+
+			default:
+				seq_printf(seq, ", Unknown Sub-Class (0x%02x)",
+					   lct->lct_entry[i].sub_class & 0xFF);
+				break;
+			}
+			break;
+
+		case I2O_CLASS_SCSI_PERIPHERAL:
+			if (lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE)
+				seq_printf(seq, ", %s",
+					   scsi_devices[lct->lct_entry[i].
+							sub_class]);
+			else
+				seq_printf(seq, ", Unknown Device Type");
+			break;
+
+		case I2O_CLASS_BUS_ADAPTER_PORT:
+			if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
+				seq_printf(seq, ", %s",
+					   bus_ports[lct->lct_entry[i].
+						     sub_class]);
+			else
+				seq_printf(seq, ", Unknown Bus Type");
+			break;
 		}
 		seq_printf(seq, "\n");
-		
-		seq_printf(seq, "  Local TID        : 0x%03x\n", lct->lct_entry[i].tid);
-		seq_printf(seq, "  User TID         : 0x%03x\n", lct->lct_entry[i].user_tid);
+
+		seq_printf(seq, "  Local TID        : 0x%03x\n",
+			   lct->lct_entry[i].tid);
+		seq_printf(seq, "  User TID         : 0x%03x\n",
+			   lct->lct_entry[i].user_tid);
 		seq_printf(seq, "  Parent TID       : 0x%03x\n",
-					lct->lct_entry[i].parent_tid);
+			   lct->lct_entry[i].parent_tid);
 		seq_printf(seq, "  Identity Tag     : 0x%x%x%x%x%x%x%x%x\n",
-					lct->lct_entry[i].identity_tag[0],
-					lct->lct_entry[i].identity_tag[1],
-					lct->lct_entry[i].identity_tag[2],
-					lct->lct_entry[i].identity_tag[3],
-					lct->lct_entry[i].identity_tag[4],
-					lct->lct_entry[i].identity_tag[5],
-					lct->lct_entry[i].identity_tag[6],
-					lct->lct_entry[i].identity_tag[7]);
+			   lct->lct_entry[i].identity_tag[0],
+			   lct->lct_entry[i].identity_tag[1],
+			   lct->lct_entry[i].identity_tag[2],
+			   lct->lct_entry[i].identity_tag[3],
+			   lct->lct_entry[i].identity_tag[4],
+			   lct->lct_entry[i].identity_tag[5],
+			   lct->lct_entry[i].identity_tag[6],
+			   lct->lct_entry[i].identity_tag[7]);
 		seq_printf(seq, "  Change Indicator : %0#10x\n",
-				lct->lct_entry[i].change_ind);
+			   lct->lct_entry[i].change_ind);
 		seq_printf(seq, "  Event Capab Mask : %0#10x\n",
-				lct->lct_entry[i].device_flags);
+			   lct->lct_entry[i].device_flags);
 	}
 
 	return 0;
@@ -559,17 +523,17 @@
 
 int i2o_seq_show_status(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)seq->private;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	char prodstr[25];
 	int version;
-	
-	i2o_status_get(c); // reread the status block
+	i2o_status_block *sb = c->status_block.virt;
+
+	i2o_status_get(c);	// reread the status block
 
-	seq_printf(seq, "Organization ID        : %0#6x\n",
-				c->status_block->org_id);
+	seq_printf(seq, "Organization ID        : %0#6x\n", sb->org_id);
+
+	version = sb->i2o_version;
 
-	version = c->status_block->i2o_version;
-	
 /* FIXME for Spec 2.0
 	if (version == 0x02) {
 		seq_printf(seq, "Lowest I2O version supported: ");
@@ -599,170 +563,171 @@
 		}
 	}
 */
-	seq_printf(seq, "IOP ID                 : %0#5x\n",
-				c->status_block->iop_id);
-	seq_printf(seq, "Host Unit ID           : %0#6x\n",
-				c->status_block->host_unit_id);
-	seq_printf(seq, "Segment Number         : %0#5x\n",
-				c->status_block->segment_number);
+	seq_printf(seq, "IOP ID                 : %0#5x\n", sb->iop_id);
+	seq_printf(seq, "Host Unit ID           : %0#6x\n", sb->host_unit_id);
+	seq_printf(seq, "Segment Number         : %0#5x\n", sb->segment_number);
 
 	seq_printf(seq, "I2O version            : ");
 	switch (version) {
-		case 0x00:
-			seq_printf(seq, "1.0\n");
-			break;
-		case 0x01:
-			seq_printf(seq, "1.5\n");
-			break;
-		case 0x02:
-			seq_printf(seq, "2.0\n");
-			break;
-		default:
-			seq_printf(seq, "Unknown version\n");
+	case 0x00:
+		seq_printf(seq, "1.0\n");
+		break;
+	case 0x01:
+		seq_printf(seq, "1.5\n");
+		break;
+	case 0x02:
+		seq_printf(seq, "2.0\n");
+		break;
+	default:
+		seq_printf(seq, "Unknown version\n");
 	}
 
 	seq_printf(seq, "IOP State              : ");
-	switch (c->status_block->iop_state) {
-		case 0x01:
-			seq_printf(seq, "INIT\n");
-			break;
+	switch (sb->iop_state) {
+	case 0x01:
+		seq_printf(seq, "INIT\n");
+		break;
 
-		case 0x02:
-			seq_printf(seq, "RESET\n");
-			break;
+	case 0x02:
+		seq_printf(seq, "RESET\n");
+		break;
 
-		case 0x04:
-			seq_printf(seq, "HOLD\n");
-			break;
+	case 0x04:
+		seq_printf(seq, "HOLD\n");
+		break;
 
-		case 0x05:
-			seq_printf(seq, "READY\n");
-			break;
+	case 0x05:
+		seq_printf(seq, "READY\n");
+		break;
 
-		case 0x08:
-			seq_printf(seq, "OPERATIONAL\n");
-			break;
+	case 0x08:
+		seq_printf(seq, "OPERATIONAL\n");
+		break;
 
-		case 0x10:
-			seq_printf(seq, "FAILED\n");
-			break;
+	case 0x10:
+		seq_printf(seq, "FAILED\n");
+		break;
 
-		case 0x11:
-			seq_printf(seq, "FAULTED\n");
-			break;
+	case 0x11:
+		seq_printf(seq, "FAULTED\n");
+		break;
 
-		default:
-			seq_printf(seq, "Unknown\n");
-			break;
+	default:
+		seq_printf(seq, "Unknown\n");
+		break;
 	}
 
 	seq_printf(seq, "Messenger Type         : ");
-	switch (c->status_block->msg_type) { 
-		case 0x00:
-			seq_printf(seq, "Memory mapped\n");
-			break;
-		case 0x01:
-			seq_printf(seq, "Memory mapped only\n");
-			break;
-		case 0x02:
-			seq_printf(seq,"Remote only\n");
-			break;
-		case 0x03:
-			seq_printf(seq, "Memory mapped and remote\n");
-			break;
-		default:
-			seq_printf(seq, "Unknown\n");
+	switch (sb->msg_type) {
+	case 0x00:
+		seq_printf(seq, "Memory mapped\n");
+		break;
+	case 0x01:
+		seq_printf(seq, "Memory mapped only\n");
+		break;
+	case 0x02:
+		seq_printf(seq, "Remote only\n");
+		break;
+	case 0x03:
+		seq_printf(seq, "Memory mapped and remote\n");
+		break;
+	default:
+		seq_printf(seq, "Unknown\n");
 	}
 
 	seq_printf(seq, "Inbound Frame Size     : %d bytes\n",
-				c->status_block->inbound_frame_size<<2);
+		   sb->inbound_frame_size << 2);
 	seq_printf(seq, "Max Inbound Frames     : %d\n",
-				c->status_block->max_inbound_frames);
+		   sb->max_inbound_frames);
 	seq_printf(seq, "Current Inbound Frames : %d\n",
-				c->status_block->cur_inbound_frames);
+		   sb->cur_inbound_frames);
 	seq_printf(seq, "Max Outbound Frames    : %d\n",
-				c->status_block->max_outbound_frames);
+		   sb->max_outbound_frames);
 
 	/* Spec doesn't say if NULL terminated or not... */
-	memcpy(prodstr, c->status_block->product_id, 24);
+	memcpy(prodstr, sb->product_id, 24);
 	prodstr[24] = '\0';
 	seq_printf(seq, "Product ID             : %s\n", prodstr);
 	seq_printf(seq, "Expected LCT Size      : %d bytes\n",
-				c->status_block->expected_lct_size);
+		   sb->expected_lct_size);
 
 	seq_printf(seq, "IOP Capabilities\n");
 	seq_printf(seq, "    Context Field Size Support : ");
-	switch (c->status_block->iop_capabilities & 0x0000003) {
-		case 0:
-			seq_printf(seq, "Supports only 32-bit context fields\n");
-			break;
-		case 1:
-			seq_printf(seq, "Supports only 64-bit context fields\n");
-			break;
-		case 2:
-			seq_printf(seq, "Supports 32-bit and 64-bit context fields, "
-						"but not concurrently\n");
-			break;
-		case 3:
-			seq_printf(seq, "Supports 32-bit and 64-bit context fields "
-						"concurrently\n");
-			break;
-		default:
-			seq_printf(seq, "0x%08x\n",c->status_block->iop_capabilities);
+	switch (sb->iop_capabilities & 0x0000003) {
+	case 0:
+		seq_printf(seq, "Supports only 32-bit context fields\n");
+		break;
+	case 1:
+		seq_printf(seq, "Supports only 64-bit context fields\n");
+		break;
+	case 2:
+		seq_printf(seq, "Supports 32-bit and 64-bit context fields, "
+			   "but not concurrently\n");
+		break;
+	case 3:
+		seq_printf(seq, "Supports 32-bit and 64-bit context fields "
+			   "concurrently\n");
+		break;
+	default:
+		seq_printf(seq, "0x%08x\n", sb->iop_capabilities);
 	}
 	seq_printf(seq, "    Current Context Field Size : ");
-	switch (c->status_block->iop_capabilities & 0x0000000C) {
-		case 0:
-			seq_printf(seq, "not configured\n");
-			break;
-		case 4:
-			seq_printf(seq, "Supports only 32-bit context fields\n");
-			break;
-		case 8:
-			seq_printf(seq, "Supports only 64-bit context fields\n");
-			break;
-		case 12:
-			seq_printf(seq, "Supports both 32-bit or 64-bit context fields "
-						"concurrently\n");
-			break;
-		default:
-			seq_printf(seq, "\n");
+	switch (sb->iop_capabilities & 0x0000000C) {
+	case 0:
+		seq_printf(seq, "not configured\n");
+		break;
+	case 4:
+		seq_printf(seq, "Supports only 32-bit context fields\n");
+		break;
+	case 8:
+		seq_printf(seq, "Supports only 64-bit context fields\n");
+		break;
+	case 12:
+		seq_printf(seq, "Supports both 32-bit or 64-bit context fields "
+			   "concurrently\n");
+		break;
+	default:
+		seq_printf(seq, "\n");
 	}
 	seq_printf(seq, "    Inbound Peer Support       : %s\n",
-			(c->status_block->iop_capabilities & 0x00000010) ? "Supported" : "Not supported");
+		   (sb->
+		    iop_capabilities & 0x00000010) ? "Supported" :
+		   "Not supported");
 	seq_printf(seq, "    Outbound Peer Support      : %s\n",
-			(c->status_block->iop_capabilities & 0x00000020) ? "Supported" : "Not supported");
+		   (sb->
+		    iop_capabilities & 0x00000020) ? "Supported" :
+		   "Not supported");
 	seq_printf(seq, "    Peer to Peer Support       : %s\n",
-			(c->status_block->iop_capabilities & 0x00000040) ? "Supported" : "Not supported");
+		   (sb->
+		    iop_capabilities & 0x00000040) ? "Supported" :
+		   "Not supported");
 
 	seq_printf(seq, "Desired private memory size   : %d kB\n",
-				c->status_block->desired_mem_size>>10);
+		   sb->desired_mem_size >> 10);
 	seq_printf(seq, "Allocated private memory size : %d kB\n",
-				c->status_block->current_mem_size>>10);
+		   sb->current_mem_size >> 10);
 	seq_printf(seq, "Private memory base address   : %0#10x\n",
-				c->status_block->current_mem_base);
+		   sb->current_mem_base);
 	seq_printf(seq, "Desired private I/O size      : %d kB\n",
-				c->status_block->desired_io_size>>10);
+		   sb->desired_io_size >> 10);
 	seq_printf(seq, "Allocated private I/O size    : %d kB\n",
-				c->status_block->current_io_size>>10);
+		   sb->current_io_size >> 10);
 	seq_printf(seq, "Private I/O base address      : %0#10x\n",
-				c->status_block->current_io_base);
+		   sb->current_io_base);
 
 	return 0;
 }
 
-int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len, 
-		     int *eof, void *data)
+int i2o_seq_show_hw(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	static u32 work32[5];
-	static u8 *work8 = (u8*)work32;
-	static u16 *work16 = (u16*)work32;
+	static u8 *work8 = (u8 *) work32;
+	static u16 *work16 = (u16 *) work32;
 	int token;
 	u32 hwcap;
 
-	static char *cpu_table[] =
-	{
+	static char *cpu_table[] = {
 		"Intel 80960 series",
 		"AMD2900 series",
 		"Motorola 68000 series",
@@ -773,397 +738,350 @@
 		"Intel x86 series"
 	};
 
-	spin_lock(&i2o_proc_lock);
-
-	len = 0;
-
-	token = i2o_query_scalar(c, ADAPTER_TID, 0x0000, -1, &work32, sizeof(work32));
+	token =
+	    i2o_parm_field_get(c->exec, 0x0000, -1, &work32, sizeof(work32));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0000 IOP Hardware");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0x0000 IOP Hardware");
+		return 0;
 	}
 
-	len += sprintf(buf+len, "I2O Vendor ID    : %0#6x\n", work16[0]);
-	len += sprintf(buf+len, "Product ID       : %0#6x\n", work16[1]);
-	len += sprintf(buf+len, "CPU              : ");
-	if(work8[16] > 8)
-		len += sprintf(buf+len, "Unknown\n");
+	seq_printf(seq, "I2O Vendor ID    : %0#6x\n", work16[0]);
+	seq_printf(seq, "Product ID       : %0#6x\n", work16[1]);
+	seq_printf(seq, "CPU              : ");
+	if (work8[16] > 8)
+		seq_printf(seq, "Unknown\n");
 	else
-		len += sprintf(buf+len, "%s\n", cpu_table[work8[16]]);
+		seq_printf(seq, "%s\n", cpu_table[work8[16]]);
 	/* Anyone using ProcessorVersion? */
-	
-	len += sprintf(buf+len, "RAM              : %dkB\n", work32[1]>>10);
-	len += sprintf(buf+len, "Non-Volatile Mem : %dkB\n", work32[2]>>10);
 
-	hwcap = work32[3];
-	len += sprintf(buf+len, "Capabilities : 0x%08x\n", hwcap);
-	len += sprintf(buf+len, "   [%s] Self booting\n",
-			(hwcap&0x00000001) ? "+" : "-");
-	len += sprintf(buf+len, "   [%s] Upgradable IRTOS\n",
-			(hwcap&0x00000002) ? "+" : "-");
-	len += sprintf(buf+len, "   [%s] Supports downloading DDMs\n",
-			(hwcap&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "   [%s] Supports installing DDMs\n",
-			(hwcap&0x00000008) ? "+" : "-");
-	len += sprintf(buf+len, "   [%s] Battery-backed RAM\n",
-			(hwcap&0x00000010) ? "+" : "-");
+	seq_printf(seq, "RAM              : %dkB\n", work32[1] >> 10);
+	seq_printf(seq, "Non-Volatile Mem : %dkB\n", work32[2] >> 10);
 
-	spin_unlock(&i2o_proc_lock);
+	hwcap = work32[3];
+	seq_printf(seq, "Capabilities : 0x%08x\n", hwcap);
+	seq_printf(seq, "   [%s] Self booting\n",
+		   (hwcap & 0x00000001) ? "+" : "-");
+	seq_printf(seq, "   [%s] Upgradable IRTOS\n",
+		   (hwcap & 0x00000002) ? "+" : "-");
+	seq_printf(seq, "   [%s] Supports downloading DDMs\n",
+		   (hwcap & 0x00000004) ? "+" : "-");
+	seq_printf(seq, "   [%s] Supports installing DDMs\n",
+		   (hwcap & 0x00000008) ? "+" : "-");
+	seq_printf(seq, "   [%s] Battery-backed RAM\n",
+		   (hwcap & 0x00000010) ? "+" : "-");
 
-	return len;
+	return 0;
 }
 
-
 /* Executive group 0003h - Executing DDM List (table) */
-int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len, 
-			    int *eof, void *data)
+int i2o_seq_show_ddm_table(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	int token;
 	int i;
 
 	typedef struct _i2o_exec_execute_ddm_table {
 		u16 ddm_tid;
-		u8  module_type;
-		u8  reserved;
+		u8 module_type;
+		u8 reserved;
 		u16 i2o_vendor_id;
 		u16 module_id;
-		u8  module_name_version[28];
+		u8 module_name_version[28];
 		u32 data_size;
 		u32 code_size;
 	} i2o_exec_execute_ddm_table;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
-		i2o_exec_execute_ddm_table ddm_table[MAX_I2O_MODULES];
+		i2o_exec_execute_ddm_table ddm_table[I2O_MAX_MODULES];
 	} *result;
 
 	i2o_exec_execute_ddm_table ddm_table;
 
 	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
+	if (!result)
 		return -ENOMEM;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID, 
-				0x0003, -1,
-				NULL, 0,
-				result, sizeof(*result));
+	token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0003, -1,
+				   NULL, 0, result, sizeof(*result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0003 Executing DDM List");
+		i2o_report_query_status(seq, token,
+					"0x0003 Executing DDM List");
 		goto out;
 	}
 
-	len += sprintf(buf+len, "Tid   Module_type     Vendor Mod_id  Module_name             Vrs  Data_size Code_size\n");
-	ddm_table=result->ddm_table[0];
+	seq_printf(seq,
+		   "Tid   Module_type     Vendor Mod_id  Module_name             Vrs  Data_size Code_size\n");
+	ddm_table = result->ddm_table[0];
 
-	for(i=0; i < result->row_count; ddm_table=result->ddm_table[++i])
-	{
-		len += sprintf(buf+len, "0x%03x ", ddm_table.ddm_tid & 0xFFF);
+	for (i = 0; i < result->row_count; ddm_table = result->ddm_table[++i]) {
+		seq_printf(seq, "0x%03x ", ddm_table.ddm_tid & 0xFFF);
 
-		switch(ddm_table.module_type)
-		{
+		switch (ddm_table.module_type) {
 		case 0x01:
-			len += sprintf(buf+len, "Downloaded DDM  ");
-			break;			
+			seq_printf(seq, "Downloaded DDM  ");
+			break;
 		case 0x22:
-			len += sprintf(buf+len, "Embedded DDM    ");
+			seq_printf(seq, "Embedded DDM    ");
 			break;
 		default:
-			len += sprintf(buf+len, "                ");
+			seq_printf(seq, "                ");
 		}
 
-		len += sprintf(buf+len, "%-#7x", ddm_table.i2o_vendor_id);
-		len += sprintf(buf+len, "%-#8x", ddm_table.module_id);
-		len += sprintf(buf+len, "%-29s", chtostr(ddm_table.module_name_version, 28));
-		len += sprintf(buf+len, "%9d  ", ddm_table.data_size);
-		len += sprintf(buf+len, "%8d", ddm_table.code_size);
+		seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id);
+		seq_printf(seq, "%-#8x", ddm_table.module_id);
+		seq_printf(seq, "%-29s",
+			   chtostr(ddm_table.module_name_version, 28));
+		seq_printf(seq, "%9d  ", ddm_table.data_size);
+		seq_printf(seq, "%8d", ddm_table.code_size);
 
-		len += sprintf(buf+len, "\n");
+		seq_printf(seq, "\n");
 	}
-out:
-	spin_unlock(&i2o_proc_lock);
+      out:
 	kfree(result);
-	return len;
+	return 0;
 }
 
-
 /* Executive group 0004h - Driver Store (scalar) */
-int i2o_proc_read_driver_store(char *buf, char **start, off_t offset, int len, 
-		     int *eof, void *data)
+int i2o_seq_show_driver_store(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	u32 work32[8];
 	int token;
 
-	spin_lock(&i2o_proc_lock);
-
-	len = 0;
-
-	token = i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32, sizeof(work32));
+	token =
+	    i2o_parm_field_get(c->exec, 0x0004, -1, &work32, sizeof(work32));
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0004 Driver Store");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0x0004 Driver Store");
+		return 0;
 	}
 
-	len += sprintf(buf+len, "Module limit  : %d\n"
-				"Module count  : %d\n"
-				"Current space : %d kB\n"
-				"Free space    : %d kB\n", 
-			work32[0], work32[1], work32[2]>>10, work32[3]>>10);
+	seq_printf(seq, "Module limit  : %d\n"
+		   "Module count  : %d\n"
+		   "Current space : %d kB\n"
+		   "Free space    : %d kB\n",
+		   work32[0], work32[1], work32[2] >> 10, work32[3] >> 10);
 
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
+	return 0;
 }
 
-
 /* Executive group 0005h - Driver Store Table (table) */
-int i2o_proc_read_drivers_stored(char *buf, char **start, off_t offset,
-				 int len, int *eof, void *data)
+int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v)
 {
 	typedef struct _i2o_driver_store {
 		u16 stored_ddm_index;
-		u8  module_type;
-		u8  reserved;
+		u8 module_type;
+		u8 reserved;
 		u16 i2o_vendor_id;
 		u16 module_id;
-		u8  module_name_version[28];
-		u8  date[8];
+		u8 module_name_version[28];
+		u8 date[8];
 		u32 module_size;
 		u32 mpb_size;
 		u32 module_flags;
 	} i2o_driver_store_table;
 
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	int token;
 	int i;
 
-	typedef struct
-	{
+	typedef struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
-		i2o_driver_store_table dst[MAX_I2O_MODULES];
+		i2o_driver_store_table dst[I2O_MAX_MODULES];
 	} i2o_driver_result_table;
-	
+
 	i2o_driver_result_table *result;
 	i2o_driver_store_table *dst;
 
-
-	len = 0;
-	
 	result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL);
-	if(result == NULL)
+	if (result == NULL)
 		return -ENOMEM;
 
-	spin_lock(&i2o_proc_lock);
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID, 0x0005, -1, NULL, 0, 
-				result, sizeof(*result));
+	token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0005, -1,
+				   NULL, 0, result, sizeof(*result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0005 DRIVER STORE TABLE");
-		spin_unlock(&i2o_proc_lock);
+		i2o_report_query_status(seq, token,
+					"0x0005 DRIVER STORE TABLE");
 		kfree(result);
-		return len;
+		return 0;
 	}
 
-	len += sprintf(buf+len, "#  Module_type     Vendor Mod_id  Module_name             Vrs"  
-				"Date     Mod_size Par_size Flags\n");
-	for(i=0, dst=&result->dst[0]; i < result->row_count; dst=&result->dst[++i])
-	{
-		len += sprintf(buf+len, "%-3d", dst->stored_ddm_index);
-		switch(dst->module_type)
-		{
+	seq_printf(seq,
+		   "#  Module_type     Vendor Mod_id  Module_name             Vrs"
+		   "Date     Mod_size Par_size Flags\n");
+	for (i = 0, dst = &result->dst[0]; i < result->row_count;
+	     dst = &result->dst[++i]) {
+		seq_printf(seq, "%-3d", dst->stored_ddm_index);
+		switch (dst->module_type) {
 		case 0x01:
-			len += sprintf(buf+len, "Downloaded DDM  ");
-			break;			
+			seq_printf(seq, "Downloaded DDM  ");
+			break;
 		case 0x22:
-			len += sprintf(buf+len, "Embedded DDM    ");
+			seq_printf(seq, "Embedded DDM    ");
 			break;
 		default:
-			len += sprintf(buf+len, "                ");
+			seq_printf(seq, "                ");
 		}
 
 #if 0
-		if(c->i2oversion == 0x02)
-			len += sprintf(buf+len, "%-d", dst->module_state);
+		if (c->i2oversion == 0x02)
+			seq_printf(seq, "%-d", dst->module_state);
 #endif
 
-		len += sprintf(buf+len, "%-#7x", dst->i2o_vendor_id);
-		len += sprintf(buf+len, "%-#8x", dst->module_id);
-		len += sprintf(buf+len, "%-29s", chtostr(dst->module_name_version,28));
-		len += sprintf(buf+len, "%-9s", chtostr(dst->date,8));
-		len += sprintf(buf+len, "%8d ", dst->module_size);
-		len += sprintf(buf+len, "%8d ", dst->mpb_size);
-		len += sprintf(buf+len, "0x%04x", dst->module_flags);
+		seq_printf(seq, "%-#7x", dst->i2o_vendor_id);
+		seq_printf(seq, "%-#8x", dst->module_id);
+		seq_printf(seq, "%-29s", chtostr(dst->module_name_version, 28));
+		seq_printf(seq, "%-9s", chtostr(dst->date, 8));
+		seq_printf(seq, "%8d ", dst->module_size);
+		seq_printf(seq, "%8d ", dst->mpb_size);
+		seq_printf(seq, "0x%04x", dst->module_flags);
 #if 0
-		if(c->i2oversion == 0x02)
-			len += sprintf(buf+len, "%d",
-				       dst->notification_level);
+		if (c->i2oversion == 0x02)
+			seq_printf(seq, "%d", dst->notification_level);
 #endif
-		len += sprintf(buf+len, "\n");
+		seq_printf(seq, "\n");
 	}
 
-	spin_unlock(&i2o_proc_lock);
 	kfree(result);
-	return len;
+	return 0;
 }
 
-
 /* Generic group F000h - Params Descriptor (table) */
-int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len, 
-			 int *eof, void *data)
+int i2o_seq_show_groups(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 	u8 properties;
 
-	typedef struct _i2o_group_info
-	{
+	typedef struct _i2o_group_info {
 		u16 group_number;
 		u16 field_count;
 		u16 row_count;
-		u8  properties;
-		u8  reserved;
+		u8 properties;
+		u8 reserved;
 	} i2o_group_info;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		i2o_group_info group[256];
 	} *result;
 
 	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
+	if (!result)
 		return -ENOMEM;
 
-	spin_lock(&i2o_proc_lock);
-
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid, 0xF000, -1, NULL, 0,
-				result, sizeof(*result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0,
+				   result, sizeof(*result));
 
 	if (token < 0) {
-		len = i2o_report_query_status(buf+len, token, "0xF000 Params Descriptor");
+		i2o_report_query_status(seq, token, "0xF000 Params Descriptor");
 		goto out;
 	}
 
-	len += sprintf(buf+len, "#  Group   FieldCount RowCount Type   Add Del Clear\n");
+	seq_printf(seq,
+		   "#  Group   FieldCount RowCount Type   Add Del Clear\n");
 
-	for (i=0; i < result->row_count; i++)
-	{
-		len += sprintf(buf+len, "%-3d", i);
-		len += sprintf(buf+len, "0x%04X ", result->group[i].group_number);
-		len += sprintf(buf+len, "%10d ", result->group[i].field_count);
-		len += sprintf(buf+len, "%8d ",  result->group[i].row_count);
+	for (i = 0; i < result->row_count; i++) {
+		seq_printf(seq, "%-3d", i);
+		seq_printf(seq, "0x%04X ", result->group[i].group_number);
+		seq_printf(seq, "%10d ", result->group[i].field_count);
+		seq_printf(seq, "%8d ", result->group[i].row_count);
 
 		properties = result->group[i].properties;
-		if (properties & 0x1)	len += sprintf(buf+len, "Table  ");
-				else	len += sprintf(buf+len, "Scalar ");
-		if (properties & 0x2)	len += sprintf(buf+len, " + ");
-				else	len += sprintf(buf+len, " - ");
-		if (properties & 0x4)	len += sprintf(buf+len, "  + ");
-				else	len += sprintf(buf+len, "  - ");
-		if (properties & 0x8)	len += sprintf(buf+len, "  + ");
-				else	len += sprintf(buf+len, "  - ");
+		if (properties & 0x1)
+			seq_printf(seq, "Table  ");
+		else
+			seq_printf(seq, "Scalar ");
+		if (properties & 0x2)
+			seq_printf(seq, " + ");
+		else
+			seq_printf(seq, " - ");
+		if (properties & 0x4)
+			seq_printf(seq, "  + ");
+		else
+			seq_printf(seq, "  - ");
+		if (properties & 0x8)
+			seq_printf(seq, "  + ");
+		else
+			seq_printf(seq, "  - ");
 
-		len += sprintf(buf+len, "\n");
+		seq_printf(seq, "\n");
 	}
 
 	if (result->more_flag)
-		len += sprintf(buf+len, "There is more...\n");
-out:
-	spin_unlock(&i2o_proc_lock);
+		seq_printf(seq, "There is more...\n");
+      out:
 	kfree(result);
-	return len;
+	return 0;
 }
 
-
 /* Generic group F001h - Physical Device Table (table) */
-int i2o_proc_read_phys_device(char *buf, char **start, off_t offset, int len,
-			      int *eof, void *data)
+int i2o_seq_show_phys_device(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		u32 adapter_id[64];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF001, -1, NULL, 0,
-				&result, sizeof(result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF001, -1, NULL, 0,
+				   &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF001 Physical Device Table");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF001 Physical Device Table");
+		return 0;
 	}
 
 	if (result.row_count)
-		len += sprintf(buf+len, "#  AdapterId\n");
+		seq_printf(seq, "#  AdapterId\n");
 
-	for (i=0; i < result.row_count; i++)
-	{
-		len += sprintf(buf+len, "%-2d", i);
-		len += sprintf(buf+len, "%#7x\n", result.adapter_id[i]);
+	for (i = 0; i < result.row_count; i++) {
+		seq_printf(seq, "%-2d", i);
+		seq_printf(seq, "%#7x\n", result.adapter_id[i]);
 	}
 
 	if (result.more_flag)
-		len += sprintf(buf+len, "There is more...\n");
+		seq_printf(seq, "There is more...\n");
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
 /* Generic group F002h - Claimed Table (table) */
-int i2o_proc_read_claimed(char *buf, char **start, off_t offset, int len,
-			  int *eof, void *data)
+int i2o_seq_show_claimed(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
@@ -1171,434 +1089,356 @@
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		u16 claimed_tid[64];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF002, -1, NULL, 0,
-				&result, sizeof(result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF002, -1, NULL, 0,
+				   &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF002 Claimed Table");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0xF002 Claimed Table");
+		return 0;
 	}
 
 	if (result.row_count)
-		len += sprintf(buf+len, "#  ClaimedTid\n");
+		seq_printf(seq, "#  ClaimedTid\n");
 
-	for (i=0; i < result.row_count; i++)
-	{
-		len += sprintf(buf+len, "%-2d", i);
-		len += sprintf(buf+len, "%#7x\n", result.claimed_tid[i]);
+	for (i = 0; i < result.row_count; i++) {
+		seq_printf(seq, "%-2d", i);
+		seq_printf(seq, "%#7x\n", result.claimed_tid[i]);
 	}
 
 	if (result.more_flag)
-		len += sprintf(buf+len, "There is more...\n");
+		seq_printf(seq, "There is more...\n");
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
 /* Generic group F003h - User Table (table) */
-int i2o_proc_read_users(char *buf, char **start, off_t offset, int len,
-			int *eof, void *data)
+int i2o_seq_show_users(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
-	typedef struct _i2o_user_table
-	{
+	typedef struct _i2o_user_table {
 		u16 instance;
 		u16 user_tid;
 		u8 claim_type;
-		u8  reserved1;
-		u16  reserved2;
+		u8 reserved1;
+		u16 reserved2;
 	} i2o_user_table;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		i2o_user_table user[64];
 	} *result;
 
 	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
+	if (!result)
 		return -ENOMEM;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF003, -1, NULL, 0,
-				result, sizeof(*result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF003, -1, NULL, 0,
+				   result, sizeof(*result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF003 User Table");
+		i2o_report_query_status(seq, token, "0xF003 User Table");
 		goto out;
 	}
 
-	len += sprintf(buf+len, "#  Instance UserTid ClaimType\n");
+	seq_printf(seq, "#  Instance UserTid ClaimType\n");
 
-	for(i=0; i < result->row_count; i++)
-	{
-		len += sprintf(buf+len, "%-3d", i);
-		len += sprintf(buf+len, "%#8x ", result->user[i].instance);
-		len += sprintf(buf+len, "%#7x ", result->user[i].user_tid);
-		len += sprintf(buf+len, "%#9x\n", result->user[i].claim_type);
+	for (i = 0; i < result->row_count; i++) {
+		seq_printf(seq, "%-3d", i);
+		seq_printf(seq, "%#8x ", result->user[i].instance);
+		seq_printf(seq, "%#7x ", result->user[i].user_tid);
+		seq_printf(seq, "%#9x\n", result->user[i].claim_type);
 	}
 
 	if (result->more_flag)
-		len += sprintf(buf+len, "There is more...\n");
-out:
-	spin_unlock(&i2o_proc_lock);
+		seq_printf(seq, "There is more...\n");
+      out:
 	kfree(result);
-	return len;
+	return 0;
 }
 
 /* Generic group F005h - Private message extensions (table) (optional) */
-int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len, 
-			    int *eof, void *data)
+int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
-	typedef struct _i2o_private
-	{
+	typedef struct _i2o_private {
 		u16 ext_instance;
 		u16 organization_id;
 		u16 x_function_code;
 	} i2o_private;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		i2o_private extension[64];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF000, -1,
-				NULL, 0,
-				&result, sizeof(result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0,
+				   &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF005 Private Message Extensions (optional)");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF005 Private Message Extensions (optional)");
+		return 0;
 	}
-	
-	len += sprintf(buf+len, "Instance#  OrgId  FunctionCode\n");
 
-	for(i=0; i < result.row_count; i++)
-	{
-		len += sprintf(buf+len, "%0#9x ", result.extension[i].ext_instance);
-		len += sprintf(buf+len, "%0#6x ", result.extension[i].organization_id);
-		len += sprintf(buf+len, "%0#6x",  result.extension[i].x_function_code);
+	seq_printf(seq, "Instance#  OrgId  FunctionCode\n");
 
-		len += sprintf(buf+len, "\n");
-	}
+	for (i = 0; i < result.row_count; i++) {
+		seq_printf(seq, "%0#9x ", result.extension[i].ext_instance);
+		seq_printf(seq, "%0#6x ", result.extension[i].organization_id);
+		seq_printf(seq, "%0#6x", result.extension[i].x_function_code);
 
-	if(result.more_flag)
-		len += sprintf(buf+len, "There is more...\n");
+		seq_printf(seq, "\n");
+	}
 
-	spin_unlock(&i2o_proc_lock);
+	if (result.more_flag)
+		seq_printf(seq, "There is more...\n");
 
-	return len;
+	return 0;
 }
 
-
 /* Generic group F006h - Authorized User Table (table) */
-int i2o_proc_read_authorized_users(char *buf, char **start, off_t offset, int len,
-				   int *eof, void *data)
+int i2o_seq_show_authorized_users(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		u32 alternate_tid[64];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF006, -1,
-				NULL, 0,
-				&result, sizeof(result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF006, -1, NULL, 0,
+				   &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF006 Autohorized User Table");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF006 Autohorized User Table");
+		return 0;
 	}
 
 	if (result.row_count)
-		len += sprintf(buf+len, "#  AlternateTid\n");
+		seq_printf(seq, "#  AlternateTid\n");
 
-	for(i=0; i < result.row_count; i++)
-	{
-		len += sprintf(buf+len, "%-2d", i);
-		len += sprintf(buf+len, "%#7x ", result.alternate_tid[i]);
+	for (i = 0; i < result.row_count; i++) {
+		seq_printf(seq, "%-2d", i);
+		seq_printf(seq, "%#7x ", result.alternate_tid[i]);
 	}
 
 	if (result.more_flag)
-		len += sprintf(buf+len, "There is more...\n");
+		seq_printf(seq, "There is more...\n");
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
-
 /* Generic group F100h - Device Identity (scalar) */
-int i2o_proc_read_dev_identity(char *buf, char **start, off_t offset, int len, 
-			       int *eof, void *data)
+int i2o_seq_show_dev_identity(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[128];		// allow for "stuff" + up to 256 byte (max) serial number
-					// == (allow) 512d bytes (max)
-	static u16 *work16 = (u16*)work32;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
+	static u32 work32[128];	// allow for "stuff" + up to 256 byte (max) serial number
+	// == (allow) 512d bytes (max)
+	static u16 *work16 = (u16 *) work32;
 	int token;
 
-	spin_lock(&i2o_proc_lock);
-	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				0xF100,	-1,
-				&work32, sizeof(work32));
+	token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token ,"0xF100 Device Identity");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0xF100 Device Identity");
+		return 0;
 	}
-	
-	len += sprintf(buf,     "Device Class  : %s\n", i2o_get_class_name(work16[0]));
-	len += sprintf(buf+len, "Owner TID     : %0#5x\n", work16[2]);
-	len += sprintf(buf+len, "Parent TID    : %0#5x\n", work16[3]);
-	len += sprintf(buf+len, "Vendor info   : %s\n", chtostr((u8 *)(work32+2), 16));
-	len += sprintf(buf+len, "Product info  : %s\n", chtostr((u8 *)(work32+6), 16));
-	len += sprintf(buf+len, "Description   : %s\n", chtostr((u8 *)(work32+10), 16));
-	len += sprintf(buf+len, "Product rev.  : %s\n", chtostr((u8 *)(work32+14), 8));
 
-	len += sprintf(buf+len, "Serial number : ");
-	len = print_serial_number(buf, len,
-			(u8*)(work32+16),
-						/* allow for SNLen plus
-						 * possible trailing '\0'
-						 */
-			sizeof(work32)-(16*sizeof(u32))-2
-				);
-	len +=  sprintf(buf+len, "\n");
+	seq_printf(seq, "Device Class  : %s\n", i2o_get_class_name(work16[0]));
+	seq_printf(seq, "Owner TID     : %0#5x\n", work16[2]);
+	seq_printf(seq, "Parent TID    : %0#5x\n", work16[3]);
+	seq_printf(seq, "Vendor info   : %s\n",
+		   chtostr((u8 *) (work32 + 2), 16));
+	seq_printf(seq, "Product info  : %s\n",
+		   chtostr((u8 *) (work32 + 6), 16));
+	seq_printf(seq, "Description   : %s\n",
+		   chtostr((u8 *) (work32 + 10), 16));
+	seq_printf(seq, "Product rev.  : %s\n",
+		   chtostr((u8 *) (work32 + 14), 8));
+
+	seq_printf(seq, "Serial number : ");
+	print_serial_number(seq, (u8 *) (work32 + 16),
+			    /* allow for SNLen plus
+			     * possible trailing '\0'
+			     */
+			    sizeof(work32) - (16 * sizeof(u32)) - 2);
+	seq_printf(seq, "\n");
 
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
+	return 0;
 }
 
-
-int i2o_proc_read_dev_name(char *buf, char **start, off_t offset, int len,
-	int *eof, void *data)
+int i2o_seq_show_dev_name(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-
-	if ( d->dev_name[0] == '\0' )
-		return 0;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 
-	len = sprintf(buf, "%s\n", d->dev_name);
+	seq_printf(seq, "%s\n", d->device.bus_id);
 
-	return len;
+	return 0;
 }
 
-
 /* Generic group F101h - DDM Identity (scalar) */
-int i2o_proc_read_ddm_identity(char *buf, char **start, off_t offset, int len, 
-			      int *eof, void *data)
+int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 
-	struct
-	{
+	struct {
 		u16 ddm_tid;
 		u8 module_name[24];
 		u8 module_rev[8];
 		u8 sn_format;
 		u8 serial_number[12];
-		u8 pad[256]; // allow up to 256 byte (max) serial number
-	} result;	
+		u8 pad[256];	// allow up to 256 byte (max) serial number
+	} result;
 
-	spin_lock(&i2o_proc_lock);
-	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid, 
-				0xF101,	-1,
-				&result, sizeof(result));
+	token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF101 DDM Identity");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0xF101 DDM Identity");
+		return 0;
 	}
 
-	len += sprintf(buf,     "Registering DDM TID : 0x%03x\n", result.ddm_tid);
-	len += sprintf(buf+len, "Module name         : %s\n", chtostr(result.module_name, 24));
-	len += sprintf(buf+len, "Module revision     : %s\n", chtostr(result.module_rev, 8));
-
-	len += sprintf(buf+len, "Serial number       : ");
-	len = print_serial_number(buf, len, result.serial_number, sizeof(result)-36);
-				/* allow for SNLen plus possible trailing '\0' */
+	seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid);
+	seq_printf(seq, "Module name         : %s\n",
+		   chtostr(result.module_name, 24));
+	seq_printf(seq, "Module revision     : %s\n",
+		   chtostr(result.module_rev, 8));
+
+	seq_printf(seq, "Serial number       : ");
+	print_serial_number(seq, result.serial_number, sizeof(result) - 36);
+	/* allow for SNLen plus possible trailing '\0' */
 
-	len += sprintf(buf+len, "\n");
+	seq_printf(seq, "\n");
 
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
+	return 0;
 }
 
 /* Generic group F102h - User Information (scalar) */
-int i2o_proc_read_uinfo(char *buf, char **start, off_t offset, int len, 
-			int *eof, void *data)
+int i2o_seq_show_uinfo(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 
- 	struct
-	{
+	struct {
 		u8 device_name[64];
 		u8 service_name[64];
 		u8 physical_location[64];
 		u8 instance_number[4];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				0xF102,	-1,
-				&result, sizeof(result));
+	token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF102 User Information");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0xF102 User Information");
+		return 0;
 	}
 
-	len += sprintf(buf,     "Device name     : %s\n", chtostr(result.device_name, 64));
-	len += sprintf(buf+len, "Service name    : %s\n", chtostr(result.service_name, 64));
-	len += sprintf(buf+len, "Physical name   : %s\n", chtostr(result.physical_location, 64));
-	len += sprintf(buf+len, "Instance number : %s\n", chtostr(result.instance_number, 4));
+	seq_printf(seq, "Device name     : %s\n",
+		   chtostr(result.device_name, 64));
+	seq_printf(seq, "Service name    : %s\n",
+		   chtostr(result.service_name, 64));
+	seq_printf(seq, "Physical name   : %s\n",
+		   chtostr(result.physical_location, 64));
+	seq_printf(seq, "Instance number : %s\n",
+		   chtostr(result.instance_number, 4));
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
 /* Generic group F103h - SGL Operating Limits (scalar) */
-int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len, 
-			     int *eof, void *data)
+int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	static u32 work32[12];
-	static u16 *work16 = (u16 *)work32;
-	static u8 *work8 = (u8 *)work32;
+	static u16 *work16 = (u16 *) work32;
+	static u8 *work8 = (u8 *) work32;
 	int token;
 
-	spin_lock(&i2o_proc_lock);
-	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid, 
-				 0xF103, -1,
-				 &work32, sizeof(work32));
+	token = i2o_parm_field_get(d, 0xF103, -1, &work32, sizeof(work32));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF103 SGL Operating Limits");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF103 SGL Operating Limits");
+		return 0;
 	}
 
-	len += sprintf(buf,     "SGL chain size        : %d\n", work32[0]);
-	len += sprintf(buf+len, "Max SGL chain size    : %d\n", work32[1]);
-	len += sprintf(buf+len, "SGL chain size target : %d\n", work32[2]);
-	len += sprintf(buf+len, "SGL frag count        : %d\n", work16[6]);
-	len += sprintf(buf+len, "Max SGL frag count    : %d\n", work16[7]);
-	len += sprintf(buf+len, "SGL frag count target : %d\n", work16[8]);
+	seq_printf(seq, "SGL chain size        : %d\n", work32[0]);
+	seq_printf(seq, "Max SGL chain size    : %d\n", work32[1]);
+	seq_printf(seq, "SGL chain size target : %d\n", work32[2]);
+	seq_printf(seq, "SGL frag count        : %d\n", work16[6]);
+	seq_printf(seq, "Max SGL frag count    : %d\n", work16[7]);
+	seq_printf(seq, "SGL frag count target : %d\n", work16[8]);
 
+/* FIXME
 	if (d->i2oversion == 0x02)
 	{
-		len += sprintf(buf+len, "SGL data alignment    : %d\n", work16[8]);
-		len += sprintf(buf+len, "SGL addr limit        : %d\n", work8[20]);
-		len += sprintf(buf+len, "SGL addr sizes supported : ");
-		if (work8[21] & 0x01)
-			len += sprintf(buf+len, "32 bit ");
-		if (work8[21] & 0x02)
-			len += sprintf(buf+len, "64 bit ");
-		if (work8[21] & 0x04)
-			len += sprintf(buf+len, "96 bit ");
-		if (work8[21] & 0x08)
-			len += sprintf(buf+len, "128 bit ");
-		len += sprintf(buf+len, "\n");
+*/
+	seq_printf(seq, "SGL data alignment    : %d\n", work16[8]);
+	seq_printf(seq, "SGL addr limit        : %d\n", work8[20]);
+	seq_printf(seq, "SGL addr sizes supported : ");
+	if (work8[21] & 0x01)
+		seq_printf(seq, "32 bit ");
+	if (work8[21] & 0x02)
+		seq_printf(seq, "64 bit ");
+	if (work8[21] & 0x04)
+		seq_printf(seq, "96 bit ");
+	if (work8[21] & 0x08)
+		seq_printf(seq, "128 bit ");
+	seq_printf(seq, "\n");
+/*
 	}
+*/
 
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
+	return 0;
 }
 
 /* Generic group F200h - Sensors (scalar) */
-int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len,
-			  int *eof, void *data)
+int i2o_seq_show_sensors(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 
-	struct
-	{
+	struct {
 		u16 sensor_instance;
-		u8  component;
+		u8 component;
 		u16 component_instance;
-		u8  sensor_class;
-		u8  sensor_type;
-		u8  scaling_exponent;
+		u8 sensor_class;
+		u8 sensor_type;
+		u8 scaling_exponent;
 		u32 actual_reading;
 		u32 minimum_reading;
 		u32 low2lowcat_treshold;
@@ -1615,1795 +1455,663 @@
 		u32 hicat2high_treshold;
 		u32 hi2hicat_treshold;
 		u32 maximum_reading;
-		u8  sensor_state;
+		u8 sensor_state;
 		u16 event_enable;
 	} result;
-	
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0xF200, -1,
-				 &result, sizeof(result));
+
+	token = i2o_parm_field_get(d, 0xF200, -1, &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF200 Sensors (optional)");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF200 Sensors (optional)");
+		return 0;
 	}
-	
-	len += sprintf(buf+len, "Sensor instance       : %d\n", result.sensor_instance);
 
-	len += sprintf(buf+len, "Component             : %d = ", result.component);
-	switch (result.component)
-	{
-	case 0:	len += sprintf(buf+len, "Other");		
-		break;
-	case 1: len += sprintf(buf+len, "Planar logic Board");
-		break;
-	case 2: len += sprintf(buf+len, "CPU");
-		break;
-	case 3: len += sprintf(buf+len, "Chassis");
-		break;
-	case 4: len += sprintf(buf+len, "Power Supply");
-		break;
-	case 5: len += sprintf(buf+len, "Storage");
-		break;
-	case 6: len += sprintf(buf+len, "External");
-		break;
-	}		
-	len += sprintf(buf+len,"\n");
+	seq_printf(seq, "Sensor instance       : %d\n", result.sensor_instance);
 
-	len += sprintf(buf+len, "Component instance    : %d\n", result.component_instance);
-	len += sprintf(buf+len, "Sensor class          : %s\n",
-				result.sensor_class ? "Analog" : "Digital");
-	
-	len += sprintf(buf+len, "Sensor type           : %d = ",result.sensor_type);
-	switch (result.sensor_type)
-	{
-	case 0:	len += sprintf(buf+len, "Other\n");
-		break;
-	case 1: len += sprintf(buf+len, "Thermal\n");
-		break;
-	case 2: len += sprintf(buf+len, "DC voltage (DC volts)\n");
-		break;
-	case 3: len += sprintf(buf+len, "AC voltage (AC volts)\n");
-		break;
-	case 4: len += sprintf(buf+len, "DC current (DC amps)\n");
-		break;
-	case 5: len += sprintf(buf+len, "AC current (AC volts)\n");
-		break;
-	case 6: len += sprintf(buf+len, "Door open\n");
-		break;
-	case 7: len += sprintf(buf+len, "Fan operational\n");
-		break;
- 	}			
-
-	len += sprintf(buf+len, "Scaling exponent      : %d\n", result.scaling_exponent);
-	len += sprintf(buf+len, "Actual reading        : %d\n", result.actual_reading);
-	len += sprintf(buf+len, "Minimum reading       : %d\n", result.minimum_reading);
-	len += sprintf(buf+len, "Low2LowCat treshold   : %d\n", result.low2lowcat_treshold);
-	len += sprintf(buf+len, "LowCat2Low treshold   : %d\n", result.lowcat2low_treshold);
-	len += sprintf(buf+len, "LowWarn2Low treshold  : %d\n", result.lowwarn2low_treshold);
-	len += sprintf(buf+len, "Low2LowWarn treshold  : %d\n", result.low2lowwarn_treshold);
-	len += sprintf(buf+len, "Norm2LowWarn treshold : %d\n", result.norm2lowwarn_treshold);
-	len += sprintf(buf+len, "LowWarn2Norm treshold : %d\n", result.lowwarn2norm_treshold);
-	len += sprintf(buf+len, "Nominal reading       : %d\n", result.nominal_reading);
-	len += sprintf(buf+len, "HiWarn2Norm treshold  : %d\n", result.hiwarn2norm_treshold);
-	len += sprintf(buf+len, "Norm2HiWarn treshold  : %d\n", result.norm2hiwarn_treshold);
-	len += sprintf(buf+len, "High2HiWarn treshold  : %d\n", result.high2hiwarn_treshold);
-	len += sprintf(buf+len, "HiWarn2High treshold  : %d\n", result.hiwarn2high_treshold);
-	len += sprintf(buf+len, "HiCat2High treshold   : %d\n", result.hicat2high_treshold);
-	len += sprintf(buf+len, "High2HiCat treshold   : %d\n", result.hi2hicat_treshold);
-	len += sprintf(buf+len, "Maximum reading       : %d\n", result.maximum_reading);
+	seq_printf(seq, "Component             : %d = ", result.component);
+	switch (result.component) {
+	case 0:
+		seq_printf(seq, "Other");
+		break;
+	case 1:
+		seq_printf(seq, "Planar logic Board");
+		break;
+	case 2:
+		seq_printf(seq, "CPU");
+		break;
+	case 3:
+		seq_printf(seq, "Chassis");
+		break;
+	case 4:
+		seq_printf(seq, "Power Supply");
+		break;
+	case 5:
+		seq_printf(seq, "Storage");
+		break;
+	case 6:
+		seq_printf(seq, "External");
+		break;
+	}
+	seq_printf(seq, "\n");
+
+	seq_printf(seq, "Component instance    : %d\n",
+		   result.component_instance);
+	seq_printf(seq, "Sensor class          : %s\n",
+		   result.sensor_class ? "Analog" : "Digital");
+
+	seq_printf(seq, "Sensor type           : %d = ", result.sensor_type);
+	switch (result.sensor_type) {
+	case 0:
+		seq_printf(seq, "Other\n");
+		break;
+	case 1:
+		seq_printf(seq, "Thermal\n");
+		break;
+	case 2:
+		seq_printf(seq, "DC voltage (DC volts)\n");
+		break;
+	case 3:
+		seq_printf(seq, "AC voltage (AC volts)\n");
+		break;
+	case 4:
+		seq_printf(seq, "DC current (DC amps)\n");
+		break;
+	case 5:
+		seq_printf(seq, "AC current (AC volts)\n");
+		break;
+	case 6:
+		seq_printf(seq, "Door open\n");
+		break;
+	case 7:
+		seq_printf(seq, "Fan operational\n");
+		break;
+	}
+
+	seq_printf(seq, "Scaling exponent      : %d\n",
+		   result.scaling_exponent);
+	seq_printf(seq, "Actual reading        : %d\n", result.actual_reading);
+	seq_printf(seq, "Minimum reading       : %d\n", result.minimum_reading);
+	seq_printf(seq, "Low2LowCat treshold   : %d\n",
+		   result.low2lowcat_treshold);
+	seq_printf(seq, "LowCat2Low treshold   : %d\n",
+		   result.lowcat2low_treshold);
+	seq_printf(seq, "LowWarn2Low treshold  : %d\n",
+		   result.lowwarn2low_treshold);
+	seq_printf(seq, "Low2LowWarn treshold  : %d\n",
+		   result.low2lowwarn_treshold);
+	seq_printf(seq, "Norm2LowWarn treshold : %d\n",
+		   result.norm2lowwarn_treshold);
+	seq_printf(seq, "LowWarn2Norm treshold : %d\n",
+		   result.lowwarn2norm_treshold);
+	seq_printf(seq, "Nominal reading       : %d\n", result.nominal_reading);
+	seq_printf(seq, "HiWarn2Norm treshold  : %d\n",
+		   result.hiwarn2norm_treshold);
+	seq_printf(seq, "Norm2HiWarn treshold  : %d\n",
+		   result.norm2hiwarn_treshold);
+	seq_printf(seq, "High2HiWarn treshold  : %d\n",
+		   result.high2hiwarn_treshold);
+	seq_printf(seq, "HiWarn2High treshold  : %d\n",
+		   result.hiwarn2high_treshold);
+	seq_printf(seq, "HiCat2High treshold   : %d\n",
+		   result.hicat2high_treshold);
+	seq_printf(seq, "High2HiCat treshold   : %d\n",
+		   result.hi2hicat_treshold);
+	seq_printf(seq, "Maximum reading       : %d\n", result.maximum_reading);
+
+	seq_printf(seq, "Sensor state          : %d = ", result.sensor_state);
+	switch (result.sensor_state) {
+	case 0:
+		seq_printf(seq, "Normal\n");
+		break;
+	case 1:
+		seq_printf(seq, "Abnormal\n");
+		break;
+	case 2:
+		seq_printf(seq, "Unknown\n");
+		break;
+	case 3:
+		seq_printf(seq, "Low Catastrophic (LoCat)\n");
+		break;
+	case 4:
+		seq_printf(seq, "Low (Low)\n");
+		break;
+	case 5:
+		seq_printf(seq, "Low Warning (LoWarn)\n");
+		break;
+	case 6:
+		seq_printf(seq, "High Warning (HiWarn)\n");
+		break;
+	case 7:
+		seq_printf(seq, "High (High)\n");
+		break;
+	case 8:
+		seq_printf(seq, "High Catastrophic (HiCat)\n");
+		break;
+	}
+
+	seq_printf(seq, "Event_enable : 0x%02X\n", result.event_enable);
+	seq_printf(seq, "    [%s] Operational state change. \n",
+		   (result.event_enable & 0x01) ? "+" : "-");
+	seq_printf(seq, "    [%s] Low catastrophic. \n",
+		   (result.event_enable & 0x02) ? "+" : "-");
+	seq_printf(seq, "    [%s] Low reading. \n",
+		   (result.event_enable & 0x04) ? "+" : "-");
+	seq_printf(seq, "    [%s] Low warning. \n",
+		   (result.event_enable & 0x08) ? "+" : "-");
+	seq_printf(seq,
+		   "    [%s] Change back to normal from out of range state. \n",
+		   (result.event_enable & 0x10) ? "+" : "-");
+	seq_printf(seq, "    [%s] High warning. \n",
+		   (result.event_enable & 0x20) ? "+" : "-");
+	seq_printf(seq, "    [%s] High reading. \n",
+		   (result.event_enable & 0x40) ? "+" : "-");
+	seq_printf(seq, "    [%s] High catastrophic. \n",
+		   (result.event_enable & 0x80) ? "+" : "-");
 
-	len += sprintf(buf+len, "Sensor state          : %d = ", result.sensor_state);
-	switch (result.sensor_state)
-	{
-	case 0:	 len += sprintf(buf+len, "Normal\n");
-		 break;
-	case 1:  len += sprintf(buf+len, "Abnormal\n");
-		 break;
-	case 2:  len += sprintf(buf+len, "Unknown\n");
-		 break;
-	case 3:  len += sprintf(buf+len, "Low Catastrophic (LoCat)\n");
-		 break;
-	case 4:  len += sprintf(buf+len, "Low (Low)\n");
-		 break;
-	case 5:  len += sprintf(buf+len, "Low Warning (LoWarn)\n");
-		 break;
-	case 6:  len += sprintf(buf+len, "High Warning (HiWarn)\n");
-		 break;
-	case 7:  len += sprintf(buf+len, "High (High)\n");
-		 break;
-	case 8:  len += sprintf(buf+len, "High Catastrophic (HiCat)\n");
-		 break;
-	}			
-
-	len += sprintf(buf+len, "Event_enable : 0x%02X\n", result.event_enable);
-	len += sprintf(buf+len, "    [%s] Operational state change. \n",
-			(result.event_enable & 0x01) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] Low catastrophic. \n",
-			(result.event_enable & 0x02) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] Low reading. \n",
-			(result.event_enable & 0x04) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] Low warning. \n",
-			(result.event_enable & 0x08) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] Change back to normal from out of range state. \n",
-			(result.event_enable & 0x10) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] High warning. \n",
-			(result.event_enable & 0x20) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] High reading. \n",
-			(result.event_enable & 0x40) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] High catastrophic. \n",
-			(result.event_enable & 0x80) ? "+" : "-" );
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
-
-static int print_serial_number(char *buff, int pos, u8 *serialno, int max_len)
+static int i2o_seq_open_hrt(struct inode *inode, struct file *file)
 {
-	int i;
-
-	/* 19990419 -sralston
-	 *	The I2O v1.5 (and v2.0 so far) "official specification"
-	 *	got serial numbers WRONG!
-	 *	Apparently, and despite what Section 3.4.4 says and
-	 *	Figure 3-35 shows (pg 3-39 in the pdf doc),
-	 *	the convention / consensus seems to be:
-	 *	  + First byte is SNFormat
-	 *	  + Second byte is SNLen (but only if SNFormat==7 (?))
-	 *	  + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format
-	 */
-	switch(serialno[0])
-	{
-		case I2O_SNFORMAT_BINARY:		/* Binary */
-			pos += sprintf(buff+pos, "0x");
-			for(i = 0; i < serialno[1]; i++)
-			{
-				pos += sprintf(buff+pos, "%02X", serialno[2+i]);
-			}
-			break;
-	
-		case I2O_SNFORMAT_ASCII:		/* ASCII */
-			if ( serialno[1] < ' ' )	/* printable or SNLen? */
-			{
-				/* sanity */
-				max_len = (max_len < serialno[1]) ? max_len : serialno[1];
-				serialno[1+max_len] = '\0';
-
-				/* just print it */
-				pos += sprintf(buff+pos, "%s", &serialno[2]);
-			}
-			else
-			{
-				/* print chars for specified length */
-				for(i = 0; i < serialno[1]; i++)
-				{
-					pos += sprintf(buff+pos, "%c", serialno[2+i]);
-				}
-			}
-			break;
-
-		case I2O_SNFORMAT_UNICODE:		/* UNICODE */
-			pos += sprintf(buff+pos, "UNICODE Format.  Can't Display\n");
-			break;
-
-		case I2O_SNFORMAT_LAN48_MAC:		/* LAN-48 MAC Address */
-			pos += sprintf(buff+pos, 
-						"LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X",
-						serialno[2], serialno[3],
-						serialno[4], serialno[5],
-						serialno[6], serialno[7]);
-			break;
-
-		case I2O_SNFORMAT_WAN:			/* WAN MAC Address */
-			/* FIXME: Figure out what a WAN access address looks like?? */
-			pos += sprintf(buff+pos, "WAN Access Address");
-			break;
-
-/* plus new in v2.0 */
-		case I2O_SNFORMAT_LAN64_MAC:		/* LAN-64 MAC Address */
-			/* FIXME: Figure out what a LAN-64 address really looks like?? */
-			pos += sprintf(buff+pos, 
-						"LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X",
-						serialno[8], serialno[9],
-						serialno[2], serialno[3],
-						serialno[4], serialno[5],
-						serialno[6], serialno[7]);
-			break;
-
-
-		case I2O_SNFORMAT_DDM:			/* I2O DDM */
-			pos += sprintf(buff+pos, 
-						"DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh",
-						*(u16*)&serialno[2],
-						*(u16*)&serialno[4],
-						*(u16*)&serialno[6]);
-			break;
-
-		case I2O_SNFORMAT_IEEE_REG64:		/* IEEE Registered (64-bit) */
-		case I2O_SNFORMAT_IEEE_REG128:		/* IEEE Registered (128-bit) */
-			/* FIXME: Figure if this is even close?? */
-			pos += sprintf(buff+pos, 
-						"IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n",
-						*(u32*)&serialno[2],
-						*(u32*)&serialno[6],
-						*(u32*)&serialno[10],
-						*(u32*)&serialno[14]);
-			break;
-
-
-		case I2O_SNFORMAT_UNKNOWN:		/* Unknown 0    */
-		case I2O_SNFORMAT_UNKNOWN2:		/* Unknown 0xff */
-		default:
-			pos += sprintf(buff+pos, "Unknown data format (0x%02x)",
-				       serialno[0]);
-			break;
-	}
-
-	return pos;
-}
+	return single_open(file, i2o_seq_show_hrt, PDE(inode)->data);
+};
 
-const char * i2o_get_connector_type(int conn)
+static int i2o_seq_open_lct(struct inode *inode, struct file *file)
 {
-	int idx = 16;
-	static char *i2o_connector_type[] = {
-		"OTHER",
-		"UNKNOWN",
-		"AUI",
-		"UTP",
-		"BNC",
-		"RJ45",
-		"STP DB9",
-		"FIBER MIC",
-		"APPLE AUI",
-		"MII",
-		"DB9",
-		"HSSDC",
-		"DUPLEX SC FIBER",
-		"DUPLEX ST FIBER",
-		"TNC/BNC",
-		"HW DEFAULT"
-	};
-
-	switch(conn)
-	{
-	case 0x00000000:
-		idx = 0;
-		break;
-	case 0x00000001:
-		idx = 1;
-		break;
-	case 0x00000002:
-		idx = 2;
-		break;
-	case 0x00000003:
-		idx = 3;
-		break;
-	case 0x00000004:
-		idx = 4;
-		break;
-	case 0x00000005:
-		idx = 5;
-		break;
-	case 0x00000006:
-		idx = 6;
-		break;
-	case 0x00000007:
-		idx = 7;
-		break;
-	case 0x00000008:
-		idx = 8;
-		break;
-	case 0x00000009:
-		idx = 9;
-		break;
-	case 0x0000000A:
-		idx = 10;
-		break;
-	case 0x0000000B:
-		idx = 11;
-		break;
-	case 0x0000000C:
-		idx = 12;
-		break;
-	case 0x0000000D:
-		idx = 13;
-		break;
-	case 0x0000000E:
-		idx = 14;
-		break;
-	case 0xFFFFFFFF:
-		idx = 15;
-		break;
-	}
-
-	return i2o_connector_type[idx];
-}
-
+	return single_open(file, i2o_seq_show_lct, PDE(inode)->data);
+};
 
-const char * i2o_get_connection_type(int conn)
+static int i2o_seq_open_status(struct inode *inode, struct file *file)
 {
-	int idx = 0;
-	static char *i2o_connection_type[] = {
-		"Unknown",
-		"AUI",
-		"10BASE5",
-		"FIORL",
-		"10BASE2",
-		"10BROAD36",
-		"10BASE-T",
-		"10BASE-FP",
-		"10BASE-FB",
-		"10BASE-FL",
-		"100BASE-TX",
-		"100BASE-FX",
-		"100BASE-T4",
-		"1000BASE-SX",
-		"1000BASE-LX",
-		"1000BASE-CX",
-		"1000BASE-T",
-		"100VG-ETHERNET",
-		"100VG-TOKEN RING",
-		"4MBIT TOKEN RING",
-		"16 Mb Token Ring",
-		"125 MBAUD FDDI",
-		"Point-to-point",
-		"Arbitrated loop",
-		"Public loop",
-		"Fabric",
-		"Emulation",
-		"Other",
-		"HW default"
-	};
-
-	switch(conn)
-	{
-	case I2O_LAN_UNKNOWN:
-		idx = 0;
-		break;
-	case I2O_LAN_AUI:
-		idx = 1;
-		break;
-	case I2O_LAN_10BASE5:
-		idx = 2;
-		break;
-	case I2O_LAN_FIORL:
-		idx = 3;
-		break;
-	case I2O_LAN_10BASE2:
-		idx = 4;
-		break;
-	case I2O_LAN_10BROAD36:
-		idx = 5;
-		break;
-	case I2O_LAN_10BASE_T:
-		idx = 6;
-		break;
-	case I2O_LAN_10BASE_FP:
-		idx = 7;
-		break;
-	case I2O_LAN_10BASE_FB:
-		idx = 8;
-		break;
-	case I2O_LAN_10BASE_FL:
-		idx = 9;
-		break;
-	case I2O_LAN_100BASE_TX:
-		idx = 10;
-		break;
-	case I2O_LAN_100BASE_FX:
-		idx = 11;
-		break;
-	case I2O_LAN_100BASE_T4:
-		idx = 12;
-		break;
-	case I2O_LAN_1000BASE_SX:
-		idx = 13;
-		break;
-	case I2O_LAN_1000BASE_LX:
-		idx = 14;
-		break;
-	case I2O_LAN_1000BASE_CX:
-		idx = 15;
-		break;
-	case I2O_LAN_1000BASE_T:
-		idx = 16;
-		break;
-	case I2O_LAN_100VG_ETHERNET:
-		idx = 17;
-		break;
-	case I2O_LAN_100VG_TR:
-		idx = 18;
-		break;
-	case I2O_LAN_4MBIT:
-		idx = 19;
-		break;
-	case I2O_LAN_16MBIT:
-		idx = 20;
-		break;
-	case I2O_LAN_125MBAUD:
-		idx = 21;
-		break;
-	case I2O_LAN_POINT_POINT:
-		idx = 22;
-		break;
-	case I2O_LAN_ARB_LOOP:
-		idx = 23;
-		break;
-	case I2O_LAN_PUBLIC_LOOP:
-		idx = 24;
-		break;
-	case I2O_LAN_FABRIC:
-		idx = 25;
-		break;
-	case I2O_LAN_EMULATION:
-		idx = 26;
-		break;
-	case I2O_LAN_OTHER:
-		idx = 27;
-		break;
-	case I2O_LAN_DEFAULT:
-		idx = 28;
-		break;
-	}
-
-	return i2o_connection_type[idx];
-}
-
+	return single_open(file, i2o_seq_show_status, PDE(inode)->data);
+};
 
-/* LAN group 0000h - Device info (scalar) */
-int i2o_proc_read_lan_dev_info(char *buf, char **start, off_t offset, int len, 
-			       int *eof, void *data)
+static int i2o_seq_open_hw(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[56];
-	static u8 *work8 = (u8*)work32;
-	static u16 *work16 = (u16*)work32;
-	static u64 *work64 = (u64*)work32;
-	int token;
-
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0000, -1, &work32, 56*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token, "0x0000 LAN Device Info");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf, "LAN Type            : ");
-	switch (work16[0])
-	{
-	case 0x0030:
-		len += sprintf(buf+len, "Ethernet, ");
-		break;
-	case 0x0040:
-		len += sprintf(buf+len, "100Base VG, ");
-		break;
-	case 0x0050:
-		len += sprintf(buf+len, "Token Ring, ");
-		break;
-	case 0x0060:
-		len += sprintf(buf+len, "FDDI, ");
-		break;
-	case 0x0070:
-		len += sprintf(buf+len, "Fibre Channel, ");
-		break;
-	default:
-		len += sprintf(buf+len, "Unknown type (0x%04x), ", work16[0]);
-		break;
-	}
-
-	if (work16[1]&0x00000001)
-		len += sprintf(buf+len, "emulated LAN, ");
-	else
-		len += sprintf(buf+len, "physical LAN port, ");
-
-	if (work16[1]&0x00000002)
-		len += sprintf(buf+len, "full duplex\n");
-	else
-		len += sprintf(buf+len, "simplex\n");
-
-	len += sprintf(buf+len, "Address format      : ");
-	switch(work8[4]) {
-	case 0x00:
-		len += sprintf(buf+len, "IEEE 48bit\n");
-		break;
-	case 0x01:
-		len += sprintf(buf+len, "FC IEEE\n");
-		break;
-	default:
-		len += sprintf(buf+len, "Unknown (0x%02x)\n", work8[4]);
-		break;
-	}
-
-	len += sprintf(buf+len, "State               : ");
-	switch(work8[5])
-	{
-	case 0x00:
-		len += sprintf(buf+len, "Unknown\n");
-		break;
-	case 0x01:
-		len += sprintf(buf+len, "Unclaimed\n");
-		break;
-	case 0x02:
-		len += sprintf(buf+len, "Operational\n");
-		break;
-	case 0x03:
-		len += sprintf(buf+len, "Suspended\n");
-		break;
-	case 0x04:
-		len += sprintf(buf+len, "Resetting\n");
-		break;
-	case 0x05:
-		len += sprintf(buf+len, "ERROR: ");
-		if(work16[3]&0x0001)
-			len += sprintf(buf+len, "TxCU inoperative ");
-		if(work16[3]&0x0002)
-			len += sprintf(buf+len, "RxCU inoperative ");
-		if(work16[3]&0x0004)
-			len += sprintf(buf+len, "Local mem alloc ");
-		len += sprintf(buf+len, "\n");
-		break;
-	case 0x06:
-		len += sprintf(buf+len, "Operational no Rx\n");
-		break;
-	case 0x07:
-		len += sprintf(buf+len, "Suspended no Rx\n");
-		break;
-	default:
-		len += sprintf(buf+len, "Unspecified\n");
-		break;
-	}
-
-	len += sprintf(buf+len, "Min packet size     : %d\n", work32[2]);
-	len += sprintf(buf+len, "Max packet size     : %d\n", work32[3]);
-	len += sprintf(buf+len, "HW address          : "
-		       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		       work8[16],work8[17],work8[18],work8[19],
-		       work8[20],work8[21],work8[22],work8[23]);
-
-	len += sprintf(buf+len, "Max Tx wire speed   : %d bps\n", (int)work64[3]);
-	len += sprintf(buf+len, "Max Rx wire speed   : %d bps\n", (int)work64[4]);
-
-	len += sprintf(buf+len, "Min SDU packet size : 0x%08x\n", work32[10]);
-	len += sprintf(buf+len, "Max SDU packet size : 0x%08x\n", work32[11]);
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+	return single_open(file, i2o_seq_show_hw, PDE(inode)->data);
+};
 
-/* LAN group 0001h - MAC address table (scalar) */
-int i2o_proc_read_lan_mac_addr(char *buf, char **start, off_t offset, int len, 
-			       int *eof, void *data)
+static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[48];
-	static u8 *work8 = (u8*)work32;
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0001, -1, &work32, 48*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0001 LAN MAC Address");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf,     "Active address          : "
-		       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		       work8[0],work8[1],work8[2],work8[3],
-		       work8[4],work8[5],work8[6],work8[7]);
-	len += sprintf(buf+len, "Current address         : "
-		       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		       work8[8],work8[9],work8[10],work8[11],
-		       work8[12],work8[13],work8[14],work8[15]);
-	len += sprintf(buf+len, "Functional address mask : "
-		       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		       work8[16],work8[17],work8[18],work8[19],
-		       work8[20],work8[21],work8[22],work8[23]);
-
-	len += sprintf(buf+len,"HW/DDM capabilities : 0x%08x\n", work32[7]);
-	len += sprintf(buf+len,"    [%s] Unicast packets supported\n",
-		       (work32[7]&0x00000001)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Promiscuous mode supported\n",
-		       (work32[7]&0x00000002)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Promiscuous multicast mode supported\n",
-		       (work32[7]&0x00000004)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Broadcast reception disabling supported\n",
-		       (work32[7]&0x00000100)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Multicast reception disabling supported\n",
-		       (work32[7]&0x00000200)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Functional address disabling supported\n",
-		       (work32[7]&0x00000400)?"+":"-");
-	len += sprintf(buf+len,"    [%s] MAC reporting supported\n",
-		       (work32[7]&0x00000800)?"+":"-");
-
-	len += sprintf(buf+len,"Filter mask : 0x%08x\n", work32[6]);
-	len += sprintf(buf+len,"    [%s] Unicast packets disable\n",
-		(work32[6]&0x00000001)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Promiscuous mode enable\n",
-		(work32[6]&0x00000002)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Promiscuous multicast mode enable\n",
-		(work32[6]&0x00000004)?"+":"-");	
-	len += sprintf(buf+len,"    [%s] Broadcast packets disable\n",
-		(work32[6]&0x00000100)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Multicast packets disable\n",
-		(work32[6]&0x00000200)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Functional address disable\n",
-		       (work32[6]&0x00000400)?"+":"-");
-		       
-	if (work32[7]&0x00000800) {
-		len += sprintf(buf+len, "    MAC reporting mode : ");
-		if (work32[6]&0x00000800)
-			len += sprintf(buf+len, "Pass only priority MAC packets to user\n");
-		else if (work32[6]&0x00001000)
-			len += sprintf(buf+len, "Pass all MAC packets to user\n");
-		else if (work32[6]&0x00001800)
-			len += sprintf(buf+len, "Pass all MAC packets (promiscuous) to user\n");
-		else
-			len += sprintf(buf+len, "Do not pass MAC packets to user\n");
-	}
-	len += sprintf(buf+len, "Number of multicast addresses : %d\n", work32[8]);
-	len += sprintf(buf+len, "Perfect filtering for max %d multicast addresses\n",
-		       work32[9]);
-	len += sprintf(buf+len, "Imperfect filtering for max %d multicast addresses\n",
-		       work32[10]);
-
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
-}
+	return single_open(file, i2o_seq_show_ddm_table, PDE(inode)->data);
+};
 
-/* LAN group 0002h - Multicast MAC address table (table) */
-int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset,
-				 int len, int *eof, void *data)
+static int i2o_seq_open_driver_store(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
-	int i;
-	u8 mc_addr[8];
-
-	struct
-	{
-		u16 result_count;
-		u16 pad;
-		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
-		u16 row_count;
-		u16 more_flag;
-		u8  mc_addr[256][8];
-	} *result;	
-
-	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
-		return -ENOMEM;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid, 0x0002, -1, 
-				NULL, 0, result, sizeof(*result));
-
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x002 LAN Multicast MAC Address");
-		goto out;
-	}
-
-	for (i = 0; i < result->row_count; i++)
-	{
-		memcpy(mc_addr, result->mc_addr[i], 8);
-
-		len += sprintf(buf+len, "MC MAC address[%d]: "
-			       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-			       i, mc_addr[0], mc_addr[1], mc_addr[2],
-			       mc_addr[3], mc_addr[4], mc_addr[5],
-			       mc_addr[6], mc_addr[7]);
-	}
-out:
-	spin_unlock(&i2o_proc_lock);
-	kfree(result);
-	return len;
-}
+	return single_open(file, i2o_seq_show_driver_store, PDE(inode)->data);
+};
 
-/* LAN group 0003h - Batch Control (scalar) */
-int i2o_proc_read_lan_batch_control(char *buf, char **start, off_t offset,
-				    int len, int *eof, void *data)
+static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[9];
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0003, -1, &work32, 9*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0003 LAN Batch Control");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf, "Batch mode ");
-	if (work32[0]&0x00000001)
-		len += sprintf(buf+len, "disabled");
-	else
-		len += sprintf(buf+len, "enabled");
-	if (work32[0]&0x00000002)
-		len += sprintf(buf+len, " (current setting)");
-	if (work32[0]&0x00000004)
-		len += sprintf(buf+len, ", forced");
-	else
-		len += sprintf(buf+len, ", toggle");
-	len += sprintf(buf+len, "\n");
-
-	len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]);
-	len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]);
-	len += sprintf(buf+len, "Max Tx batch delay : %d\n", work32[7]);
-	len += sprintf(buf+len, "Max Tx batch count : %d\n", work32[8]);
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+	return single_open(file, i2o_seq_show_drivers_stored, PDE(inode)->data);
+};
 
-/* LAN group 0004h - LAN Operation (scalar) */
-int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len,
-				int *eof, void *data)
+static int i2o_seq_open_groups(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[5];
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
+	return single_open(file, i2o_seq_show_groups, PDE(inode)->data);
+};
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0004, -1, &work32, 20);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0004 LAN Operation");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf, "Packet prepadding (32b words) : %d\n", work32[0]);
-	len += sprintf(buf+len, "Transmission error reporting  : %s\n",
-		       (work32[1]&1)?"on":"off");
-	len += sprintf(buf+len, "Bad packet handling           : %s\n",
-				(work32[1]&0x2)?"by host":"by DDM");
-	len += sprintf(buf+len, "Packet orphan limit           : %d\n", work32[2]);
-
-	len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[3]);
-	len += sprintf(buf+len, "    [%s] HW CRC suppression\n",
-			(work32[3]&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW IPv4 checksum\n",
-			(work32[3]&0x00000100) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW TCP checksum\n",
-			(work32[3]&0x00000200) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW UDP checksum\n",
-			(work32[3]&0x00000400) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW RSVP checksum\n",
-			(work32[3]&0x00000800) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW ICMP checksum\n",
-			(work32[3]&0x00001000) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] Loopback suppression enable\n",
-			(work32[3]&0x00002000) ? "+" : "-");
-
-	len += sprintf(buf+len, "Rx modes : 0x%08x\n", work32[4]);
-	len += sprintf(buf+len, "    [%s] FCS in payload\n",
-			(work32[4]&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW IPv4 checksum validation\n",
-			(work32[4]&0x00000100) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW TCP checksum validation\n",
-			(work32[4]&0x00000200) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW UDP checksum validation\n",
-			(work32[4]&0x00000400) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW RSVP checksum validation\n",
-			(work32[4]&0x00000800) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW ICMP checksum validation\n",
-			(work32[4]&0x00001000) ? "+" : "-");
- 
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0005h - Media operation (scalar) */
-int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset,
-				      int len, int *eof, void *data)
+static int i2o_seq_open_phys_device(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
-
-	struct
-	{
-		u32 connector_type;
-		u32 connection_type;
-		u64 current_tx_wire_speed;
-		u64 current_rx_wire_speed;
-		u8  duplex_mode;
-		u8  link_status;
-		u8  reserved;
-		u8  duplex_mode_target;
-		u32 connector_type_target;
-		u32 connection_type_target;
-	} result;	
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0005, -1, &result, sizeof(result));
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token, "0x0005 LAN Media Operation");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf, "Connector type         : %s\n",
-		       i2o_get_connector_type(result.connector_type));
-	len += sprintf(buf+len, "Connection type        : %s\n",
-		       i2o_get_connection_type(result.connection_type));
-
-	len += sprintf(buf+len, "Current Tx wire speed  : %d bps\n", (int)result.current_tx_wire_speed);
-	len += sprintf(buf+len, "Current Rx wire speed  : %d bps\n", (int)result.current_rx_wire_speed);
-	len += sprintf(buf+len, "Duplex mode            : %s duplex\n",
-			(result.duplex_mode)?"Full":"Half");
-			
-	len += sprintf(buf+len, "Link status            : ");
-	switch (result.link_status)
-	{
-	case 0x00:
-		len += sprintf(buf+len, "Unknown\n");
-		break;
-	case 0x01:
-		len += sprintf(buf+len, "Normal\n");
-		break;
-	case 0x02:
-		len += sprintf(buf+len, "Failure\n");
-		break;
-	case 0x03:
-		len += sprintf(buf+len, "Reset\n");
-		break;
-	default:
-		len += sprintf(buf+len, "Unspecified\n");
-	}
-	
-	len += sprintf(buf+len, "Duplex mode target     : ");
-	switch (result.duplex_mode_target){
-		case 0:
-			len += sprintf(buf+len, "Half duplex\n");
-			break;
-		case 1:
-			len += sprintf(buf+len, "Full duplex\n");
-			break;
-		default:
-			len += sprintf(buf+len, "\n");
-	}
-
-	len += sprintf(buf+len, "Connector type target  : %s\n",
-		       i2o_get_connector_type(result.connector_type_target));
-	len += sprintf(buf+len, "Connection type target : %s\n",
-		       i2o_get_connection_type(result.connection_type_target));
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+	return single_open(file, i2o_seq_show_phys_device, PDE(inode)->data);
+};
 
-/* LAN group 0006h - Alternate address (table) (optional) */
-int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len,
-			       int *eof, void *data)
+static int i2o_seq_open_claimed(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
-	int i;
-	u8 alt_addr[8];
-	struct
-	{
-		u16 result_count;
-		u16 pad;
-		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
-		u16 row_count;
-		u16 more_flag;
-		u8  alt_addr[256][8];
-	} *result;	
-
-	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
-		return -ENOMEM;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0x0006, -1, NULL, 0, result, sizeof(*result));
-
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token, "0x0006 LAN Alternate Address (optional)");
-		goto out;
-	}
-
-	for (i=0; i < result->row_count; i++)
-	{
-		memcpy(alt_addr,result->alt_addr[i],8);
-		len += sprintf(buf+len, "Alternate address[%d]: "
-			       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-			       i, alt_addr[0], alt_addr[1], alt_addr[2],
-			       alt_addr[3], alt_addr[4], alt_addr[5],
-			       alt_addr[6], alt_addr[7]);
-	}
-out:
-	spin_unlock(&i2o_proc_lock);
-	kfree(result);
-	return len;
-}
-
+	return single_open(file, i2o_seq_show_claimed, PDE(inode)->data);
+};
 
-/* LAN group 0007h - Transmit info (scalar) */
-int i2o_proc_read_lan_tx_info(char *buf, char **start, off_t offset, int len, 
-			      int *eof, void *data)
+static int i2o_seq_open_users(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[8];
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
+	return single_open(file, i2o_seq_show_users, PDE(inode)->data);
+};
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0007, -1, &work32, 8*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0007 LAN Transmit Info");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf,     "Tx Max SG elements per packet : %d\n", work32[0]);
-	len += sprintf(buf+len, "Tx Max SG elements per chain  : %d\n", work32[1]);
-	len += sprintf(buf+len, "Tx Max outstanding packets    : %d\n", work32[2]);
-	len += sprintf(buf+len, "Tx Max packets per request    : %d\n", work32[3]);
-
-	len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[4]);
-	len += sprintf(buf+len, "    [%s] No DA in SGL\n",
-				(work32[4]&0x00000002) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] CRC suppression\n",
-				(work32[4]&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] MAC insertion\n",
-				(work32[4]&0x00000010) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] RIF insertion\n",
-				(work32[4]&0x00000020) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] IPv4 checksum generation\n",
-				(work32[4]&0x00000100) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] TCP checksum generation\n",
-				(work32[4]&0x00000200) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] UDP checksum generation\n",
-				(work32[4]&0x00000400) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] RSVP checksum generation\n",
-				(work32[4]&0x00000800) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] ICMP checksum generation\n",
-				(work32[4]&0x00001000) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] Loopback enabled\n",
-				(work32[4]&0x00010000) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] Loopback suppression enabled\n",
-				(work32[4]&0x00020000) ? "+" : "-");
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0008h - Receive info (scalar) */
-int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len, 
-			      int *eof, void *data)
+static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[8];
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0008, -1, &work32, 8*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0008 LAN Receive Info");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf     ,"Rx Max size of chain element : %d\n", work32[0]);
-	len += sprintf(buf+len, "Rx Max Buckets               : %d\n", work32[1]);
-	len += sprintf(buf+len, "Rx Max Buckets in Reply      : %d\n", work32[3]);
-	len += sprintf(buf+len, "Rx Max Packets in Bucket     : %d\n", work32[4]);
-	len += sprintf(buf+len, "Rx Max Buckets in Post       : %d\n", work32[5]);
-
-	len += sprintf(buf+len, "Rx Modes : 0x%08x\n", work32[2]);
-	len += sprintf(buf+len, "    [%s] FCS reception\n",
-				(work32[2]&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] IPv4 checksum validation \n",
-				(work32[2]&0x00000100) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] TCP checksum validation \n",
-				(work32[2]&0x00000200) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] UDP checksum validation \n",
-				(work32[2]&0x00000400) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] RSVP checksum validation \n",
-				(work32[2]&0x00000800) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] ICMP checksum validation \n",
-				(work32[2]&0x00001000) ? "+" : "-");
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-static int i2o_report_opt_field(char *buf, char *field_name,
-				int field_nbr, int supp_fields, u64 *value)
-{
-	if (supp_fields & (1 << field_nbr))
-		return sprintf(buf, "%-24s : " FMT_U64_HEX "\n", field_name, U64_VAL(value));
-	else	
-		return sprintf(buf, "%-24s : Not supported\n", field_name);	
-}
-
-/* LAN group 0100h - LAN Historical statistics (scalar) */
-/* LAN group 0180h - Supported Optional Historical Statistics (scalar) */
-/* LAN group 0182h - Optional Non Media Specific Transmit Historical Statistics (scalar) */
-/* LAN group 0183h - Optional Non Media Specific Receive Historical Statistics (scalar) */
+	return single_open(file, i2o_seq_show_priv_msgs, PDE(inode)->data);
+};
 
-int i2o_proc_read_lan_hist_stats(char *buf, char **start, off_t offset, int len,
-				 int *eof, void *data)
+static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
-
-	struct
-	{
-		u64 tx_packets;
-		u64 tx_bytes;
-		u64 rx_packets;
-		u64 rx_bytes;
-		u64 tx_errors;
-		u64 rx_errors;
-		u64 rx_dropped;
-		u64 adapter_resets;
-		u64 adapter_suspends;
-	} stats;			// 0x0100
-
-	static u64 supp_groups[4];	// 0x0180
-
-	struct
-	{
-		u64 tx_retries;
-		u64 tx_directed_bytes;
-		u64 tx_directed_packets;
-		u64 tx_multicast_bytes;
-		u64 tx_multicast_packets;
-		u64 tx_broadcast_bytes;
-		u64 tx_broadcast_packets;
-		u64 tx_group_addr_packets;
-		u64 tx_short_packets;
-	} tx_stats;			// 0x0182
-
-	struct
-	{
-		u64 rx_crc_errors;
-		u64 rx_directed_bytes;
-		u64 rx_directed_packets;
-		u64 rx_multicast_bytes;
-		u64 rx_multicast_packets;
-		u64 rx_broadcast_bytes;
-		u64 rx_broadcast_packets;
-		u64 rx_group_addr_packets;
-		u64 rx_short_packets;
-		u64 rx_long_packets;
-		u64 rx_runt_packets;
-	} rx_stats;			// 0x0183
-
-	struct
-	{
-		u64 ipv4_generate;
-		u64 ipv4_validate_success;
-		u64 ipv4_validate_errors;
-		u64 tcp_generate;
-		u64 tcp_validate_success;
-		u64 tcp_validate_errors;
-		u64 udp_generate;
-		u64 udp_validate_success;
-		u64 udp_validate_errors;
-		u64 rsvp_generate;
-		u64 rsvp_validate_success;
-		u64 rsvp_validate_errors;		
-		u64 icmp_generate;
-		u64 icmp_validate_success;
-		u64 icmp_validate_errors;
-	} chksum_stats;			// 0x0184
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0100, -1, &stats, sizeof(stats));
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x100 LAN Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf+len, "Tx packets       : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_packets));
-	len += sprintf(buf+len, "Tx bytes         : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_bytes));
-	len += sprintf(buf+len, "Rx packets       : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_packets));
-	len += sprintf(buf+len, "Rx bytes         : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_bytes));
-	len += sprintf(buf+len, "Tx errors        : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_errors));
-	len += sprintf(buf+len, "Rx errors        : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_errors));
-	len += sprintf(buf+len, "Rx dropped       : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_dropped));
-	len += sprintf(buf+len, "Adapter resets   : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.adapter_resets));
-	len += sprintf(buf+len, "Adapter suspends : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.adapter_suspends));
-
-	/* Optional statistics follows */
-	/* Get 0x0180 to see which optional groups/fields are supported */
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0180, -1, &supp_groups, sizeof(supp_groups));
-	
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token, "0x180 LAN Supported Optional Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	if (supp_groups[1]) /* 0x0182 */
-	{
-		token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 	0x0182, -1, &tx_stats, sizeof(tx_stats));
-
-		if (token < 0) {
-			len += i2o_report_query_status(buf+len, token,"0x182 LAN Optional Tx Historical Statistics");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
-
-		len += sprintf(buf+len, "==== Optional TX statistics (group 0182h)\n");
-
-		len += i2o_report_opt_field(buf+len, "Tx RetryCount",
-					0, supp_groups[1], &tx_stats.tx_retries);
-		len += i2o_report_opt_field(buf+len, "Tx DirectedBytes",
-					1, supp_groups[1], &tx_stats.tx_directed_bytes);
-		len += i2o_report_opt_field(buf+len, "Tx DirectedPackets",
-					2, supp_groups[1], &tx_stats.tx_directed_packets);
-		len += i2o_report_opt_field(buf+len, "Tx MulticastBytes",
-					3, supp_groups[1], &tx_stats.tx_multicast_bytes);
-		len += i2o_report_opt_field(buf+len, "Tx MulticastPackets",
-					4, supp_groups[1], &tx_stats.tx_multicast_packets);
-		len += i2o_report_opt_field(buf+len, "Tx BroadcastBytes",
-					5, supp_groups[1], &tx_stats.tx_broadcast_bytes);
-		len += i2o_report_opt_field(buf+len, "Tx BroadcastPackets",
-					6, supp_groups[1], &tx_stats.tx_broadcast_packets);
-		len += i2o_report_opt_field(buf+len, "Tx TotalGroupAddrPackets",
-					7, supp_groups[1], &tx_stats.tx_group_addr_packets);
-		len += i2o_report_opt_field(buf+len, "Tx TotalPacketsTooShort",
-					8, supp_groups[1], &tx_stats.tx_short_packets);
-	}
-
-	if (supp_groups[2]) /* 0x0183 */
-	{
-		token = i2o_query_scalar(d->controller, d->lct_data.tid,
-					 0x0183, -1, &rx_stats, sizeof(rx_stats));
-		if (token < 0) {
-			len += i2o_report_query_status(buf+len, token,"0x183 LAN Optional Rx Historical Stats");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+	return single_open(file, i2o_seq_show_authorized_users,
+			   PDE(inode)->data);
+};
 
-		len += sprintf(buf+len, "==== Optional RX statistics (group 0183h)\n");
+static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_dev_identity, PDE(inode)->data);
+};
 
-		len += i2o_report_opt_field(buf+len, "Rx CRCErrorCount",
-					0, supp_groups[2], &rx_stats.rx_crc_errors);
-		len += i2o_report_opt_field(buf+len, "Rx DirectedBytes",
-					1, supp_groups[2], &rx_stats.rx_directed_bytes);
-		len += i2o_report_opt_field(buf+len, "Rx DirectedPackets",
-					2, supp_groups[2], &rx_stats.rx_directed_packets);
-		len += i2o_report_opt_field(buf+len, "Rx MulticastBytes",
-					3, supp_groups[2], &rx_stats.rx_multicast_bytes);
-		len += i2o_report_opt_field(buf+len, "Rx MulticastPackets",
-					4, supp_groups[2], &rx_stats.rx_multicast_packets);
-		len += i2o_report_opt_field(buf+len, "Rx BroadcastBytes",
-					5, supp_groups[2], &rx_stats.rx_broadcast_bytes);
-		len += i2o_report_opt_field(buf+len, "Rx BroadcastPackets",
-					6, supp_groups[2], &rx_stats.rx_broadcast_packets);
-		len += i2o_report_opt_field(buf+len, "Rx TotalGroupAddrPackets",
-					7, supp_groups[2], &rx_stats.rx_group_addr_packets);
-		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooShort",
-					8, supp_groups[2], &rx_stats.rx_short_packets);
-		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooLong",
-					9, supp_groups[2], &rx_stats.rx_long_packets);
-		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsRunt",
-					10, supp_groups[2], &rx_stats.rx_runt_packets);
-	}
-	
-	if (supp_groups[3]) /* 0x0184 */
-	{
-		token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 	0x0184, -1, &chksum_stats, sizeof(chksum_stats));
+static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_ddm_identity, PDE(inode)->data);
+};
 
-		if (token < 0) {
-			len += i2o_report_query_status(buf+len, token,"0x184 LAN Optional Chksum Historical Stats");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+static int i2o_seq_open_uinfo(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_uinfo, PDE(inode)->data);
+};
 
-		len += sprintf(buf+len, "==== Optional CHKSUM statistics (group 0x0184)\n");
+static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_sgl_limits, PDE(inode)->data);
+};
 
-		len += i2o_report_opt_field(buf+len, "IPv4 Generate",
-					0, supp_groups[3], &chksum_stats.ipv4_generate);
-		len += i2o_report_opt_field(buf+len, "IPv4 ValidateSuccess",
-					1, supp_groups[3], &chksum_stats.ipv4_validate_success);
-		len += i2o_report_opt_field(buf+len, "IPv4 ValidateError",
-					2, supp_groups[3], &chksum_stats.ipv4_validate_errors);
-		len += i2o_report_opt_field(buf+len, "TCP  Generate",
-					3, supp_groups[3], &chksum_stats.tcp_generate);
-		len += i2o_report_opt_field(buf+len, "TCP  ValidateSuccess",
-					4, supp_groups[3], &chksum_stats.tcp_validate_success);
-		len += i2o_report_opt_field(buf+len, "TCP  ValidateError",
-					5, supp_groups[3], &chksum_stats.tcp_validate_errors);
-		len += i2o_report_opt_field(buf+len, "UDP  Generate",
-					6, supp_groups[3], &chksum_stats.udp_generate);
-		len += i2o_report_opt_field(buf+len, "UDP  ValidateSuccess",
-					7, supp_groups[3], &chksum_stats.udp_validate_success);
-		len += i2o_report_opt_field(buf+len, "UDP  ValidateError",
-					8, supp_groups[3], &chksum_stats.udp_validate_errors);
-		len += i2o_report_opt_field(buf+len, "RSVP Generate",
-					9, supp_groups[3], &chksum_stats.rsvp_generate);
-		len += i2o_report_opt_field(buf+len, "RSVP ValidateSuccess",
-					10, supp_groups[3], &chksum_stats.rsvp_validate_success);
-		len += i2o_report_opt_field(buf+len, "RSVP ValidateError",
-					11, supp_groups[3], &chksum_stats.rsvp_validate_errors);
-		len += i2o_report_opt_field(buf+len, "ICMP Generate",
-					12, supp_groups[3], &chksum_stats.icmp_generate);
-		len += i2o_report_opt_field(buf+len, "ICMP ValidateSuccess",
-					13, supp_groups[3], &chksum_stats.icmp_validate_success);
-		len += i2o_report_opt_field(buf+len, "ICMP ValidateError",
-					14, supp_groups[3], &chksum_stats.icmp_validate_errors);
-	}
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0200h - Required Ethernet Statistics (scalar) */
-/* LAN group 0280h - Optional Ethernet Statistics Supported (scalar) */
-/* LAN group 0281h - Optional Ethernet Historical Statistics (scalar) */
-int i2o_proc_read_lan_eth_stats(char *buf, char **start, off_t offset,
-				int len, int *eof, void *data)
+static int i2o_seq_open_sensors(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
+	return single_open(file, i2o_seq_show_sensors, PDE(inode)->data);
+};
 
-	struct
-	{
-		u64 rx_align_errors;
-		u64 tx_one_collisions;
-		u64 tx_multiple_collisions;
-		u64 tx_deferred;
-		u64 tx_late_collisions;
-		u64 tx_max_collisions;
-		u64 tx_carrier_lost;
-		u64 tx_excessive_deferrals;
-	} stats;	
+static int i2o_seq_open_dev_name(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data);
+};
 
-	static u64 supp_fields;
-	struct
-	{
-		u64 rx_overrun;
-		u64 tx_underrun;
-		u64 tx_heartbeat_failure;	
-	} hist_stats;
+static struct file_operations i2o_seq_fops_lct = {
+	.open = i2o_seq_open_lct,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
+static struct file_operations i2o_seq_fops_hrt = {
+	.open = i2o_seq_open_hrt,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0200, -1, &stats, sizeof(stats));
+static struct file_operations i2o_seq_fops_status = {
+	.open = i2o_seq_open_status,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0200 LAN Ethernet Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf+len, "Rx alignment errors    : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_align_errors));
-	len += sprintf(buf+len, "Tx one collisions      : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_one_collisions));
-	len += sprintf(buf+len, "Tx multicollisions     : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_multiple_collisions));
-	len += sprintf(buf+len, "Tx deferred            : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_deferred));
-	len += sprintf(buf+len, "Tx late collisions     : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_late_collisions));
-	len += sprintf(buf+len, "Tx max collisions      : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_max_collisions));
-	len += sprintf(buf+len, "Tx carrier lost        : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_carrier_lost));
-	len += sprintf(buf+len, "Tx excessive deferrals : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_excessive_deferrals));
+static struct file_operations i2o_seq_fops_hw = {
+	.open = i2o_seq_open_hw,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	/* Optional Ethernet statistics follows  */
-	/* Get 0x0280 to see which optional fields are supported */
+static struct file_operations i2o_seq_fops_ddm_table = {
+	.open = i2o_seq_open_ddm_table,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0280, -1, &supp_fields, sizeof(supp_fields));
+static struct file_operations i2o_seq_fops_driver_store = {
+	.open = i2o_seq_open_driver_store,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0280 LAN Supported Optional Ethernet Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
+static struct file_operations i2o_seq_fops_drivers_stored = {
+	.open = i2o_seq_open_drivers_stored,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	if (supp_fields) /* 0x0281 */
-	{
-		token = i2o_query_scalar(d->controller, d->lct_data.tid,
-					 0x0281, -1, &stats, sizeof(stats));
+static struct file_operations i2o_seq_fops_groups = {
+	.open = i2o_seq_open_groups,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-		if (token < 0) {
-			len += i2o_report_query_status(buf+len, token,"0x0281 LAN Optional Ethernet Statistics");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+static struct file_operations i2o_seq_fops_phys_device = {
+	.open = i2o_seq_open_phys_device,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-		len += sprintf(buf+len, "==== Optional ETHERNET statistics (group 0x0281)\n");
+static struct file_operations i2o_seq_fops_claimed = {
+	.open = i2o_seq_open_claimed,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-		len += i2o_report_opt_field(buf+len, "Rx Overrun",
-					0, supp_fields, &hist_stats.rx_overrun);
-		len += i2o_report_opt_field(buf+len, "Tx Underrun",
-					1, supp_fields, &hist_stats.tx_underrun);
-		len += i2o_report_opt_field(buf+len, "Tx HeartbeatFailure",
-					2, supp_fields, &hist_stats.tx_heartbeat_failure);
-	}
+static struct file_operations i2o_seq_fops_users = {
+	.open = i2o_seq_open_users,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+static struct file_operations i2o_seq_fops_priv_msgs = {
+	.open = i2o_seq_open_priv_msgs,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-/* LAN group 0300h - Required Token Ring Statistics (scalar) */
-/* LAN group 0380h, 0381h - Optional Statistics not yet defined (TODO) */
-int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset,
-			       int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[13];
-	int token;
+static struct file_operations i2o_seq_fops_authorized_users = {
+	.open = i2o_seq_open_authorized_users,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	static char *ring_status[] =
-	{
-		"",
-		"",
-		"",
-		"",
-		"",
-		"Ring Recovery",
-		"Single Station",
-		"Counter Overflow",
-		"Remove Received",
-		"",
-		"Auto-Removal Error 1",
-		"Lobe Wire Fault",
-		"Transmit Beacon",
-		"Soft Error",
-		"Hard Error",
-		"Signal Loss"
-	};
+static struct file_operations i2o_seq_fops_dev_name = {
+	.open = i2o_seq_open_dev_name,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
+static struct file_operations i2o_seq_fops_dev_identity = {
+	.open = i2o_seq_open_dev_identity,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0300, -1, &work64, sizeof(work64));
+static struct file_operations i2o_seq_fops_ddm_identity = {
+	.open = i2o_seq_open_ddm_identity,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0300 Token Ring Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf,     "LineErrors          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[0]));
-	len += sprintf(buf+len, "LostFrames          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
-	len += sprintf(buf+len, "ACError             : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
-	len += sprintf(buf+len, "TxAbortDelimiter    : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[3]));
-	len += sprintf(buf+len, "BursErrors          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[4]));
-	len += sprintf(buf+len, "FrameCopiedErrors   : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[5]));
-	len += sprintf(buf+len, "FrequencyErrors     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[6]));
-	len += sprintf(buf+len, "InternalErrors      : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[7]));
-	len += sprintf(buf+len, "LastRingStatus      : %s\n", ring_status[work64[8]]);
-	len += sprintf(buf+len, "TokenError          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[9]));
-	len += sprintf(buf+len, "UpstreamNodeAddress : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[10]));
-	len += sprintf(buf+len, "LastRingID          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[11]));
-	len += sprintf(buf+len, "LastBeaconType      : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[12]));
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0400h - Required FDDI Statistics (scalar) */
-/* LAN group 0480h, 0481h - Optional Statistics, not yet defined (TODO) */
-int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset,
-				 int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[11];
-	int token;
+static struct file_operations i2o_seq_fops_uinfo = {
+	.open = i2o_seq_open_uinfo,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	static char *conf_state[] =
-	{
-		"Isolated",
-		"Local a",
-		"Local b",
-		"Local ab",
-		"Local s",
-		"Wrap a",
-		"Wrap b",
-		"Wrap ab",
-		"Wrap s",
-		"C-Wrap a",
-		"C-Wrap b",
-		"C-Wrap s",
-		"Through",
-	};
+static struct file_operations i2o_seq_fops_sgl_limits = {
+	.open = i2o_seq_open_sgl_limits,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	static char *ring_state[] =
-	{
-		"Isolated",
-		"Non-op",
-		"Rind-op",
-		"Detect",
-		"Non-op-Dup",
-		"Ring-op-Dup",
-		"Directed",
-		"Trace"
-	};
+static struct file_operations i2o_seq_fops_sensors = {
+	.open = i2o_seq_open_sensors,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	static char *link_state[] =
-	{
-		"Off",
-		"Break",
-		"Trace",
-		"Connect",
-		"Next",
-		"Signal",
-		"Join",
-		"Verify",
-		"Active",
-		"Maintenance"
-	};
+/*
+ * IOP specific entries...write field just in case someone
+ * ever wants one.
+ */
+static i2o_proc_entry i2o_proc_generic_iop_entries[] = {
+	{"hrt", S_IFREG | S_IRUGO, &i2o_seq_fops_hrt},
+	{"lct", S_IFREG | S_IRUGO, &i2o_seq_fops_lct},
+	{"status", S_IFREG | S_IRUGO, &i2o_seq_fops_status},
+	{"hw", S_IFREG | S_IRUGO, &i2o_seq_fops_hw},
+	{"ddm_table", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_table},
+	{"driver_store", S_IFREG | S_IRUGO, &i2o_seq_fops_driver_store},
+	{"drivers_stored", S_IFREG | S_IRUGO, &i2o_seq_fops_drivers_stored},
+	{NULL, 0, NULL}
+};
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
+/*
+ * Device specific entries
+ */
+static i2o_proc_entry generic_dev_entries[] = {
+	{"groups", S_IFREG | S_IRUGO, &i2o_seq_fops_groups},
+	{"phys_dev", S_IFREG | S_IRUGO, &i2o_seq_fops_phys_device},
+	{"claimed", S_IFREG | S_IRUGO, &i2o_seq_fops_claimed},
+	{"users", S_IFREG | S_IRUGO, &i2o_seq_fops_users},
+	{"priv_msgs", S_IFREG | S_IRUGO, &i2o_seq_fops_priv_msgs},
+	{"authorized_users", S_IFREG | S_IRUGO, &i2o_seq_fops_authorized_users},
+	{"dev_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_identity},
+	{"ddm_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_identity},
+	{"user_info", S_IFREG | S_IRUGO, &i2o_seq_fops_uinfo},
+	{"sgl_limits", S_IFREG | S_IRUGO, &i2o_seq_fops_sgl_limits},
+	{"sensors", S_IFREG | S_IRUGO, &i2o_seq_fops_sensors},
+	{NULL, 0, NULL}
+};
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0400, -1, &work64, sizeof(work64));
+/*
+ *  Storage unit specific entries (SCSI Periph, BS) with device names
+ */
+static i2o_proc_entry rbs_dev_entries[] = {
+	{"dev_name", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_name},
+	{NULL, 0, NULL}
+};
 
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0400 FDDI Required Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf+len, "ConfigurationState : %s\n", conf_state[work64[0]]);
-	len += sprintf(buf+len, "UpstreamNode       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
-	len += sprintf(buf+len, "DownStreamNode     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
-	len += sprintf(buf+len, "FrameErrors        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[3]));
-	len += sprintf(buf+len, "FramesLost         : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[4]));
-	len += sprintf(buf+len, "RingMgmtState      : %s\n", ring_state[work64[5]]);
-	len += sprintf(buf+len, "LCTFailures        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[6]));
-	len += sprintf(buf+len, "LEMRejects         : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[7]));
-	len += sprintf(buf+len, "LEMCount           : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[8]));
-	len += sprintf(buf+len, "LConnectionState   : %s\n",
-		       link_state[work64[9]]);
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-static int i2o_proc_create_entries(void *data, i2o_proc_entry *pentry,
-				   struct proc_dir_entry *parent)
-{
-	struct proc_dir_entry *ent;
-	
-	while(pentry->name != NULL)
-	{
-		ent = create_proc_entry(pentry->name, pentry->mode, parent);
-		if(!ent) return -1;
+/**
+ *	i2o_proc_create_entries - Creates proc dir entries
+ *	@dir: proc dir entry under which the entries should be placed
+ *	@i2o_pe: pointer to the entries which should be added
+ *	@data: pointer to I2O controller or device
+ *
+ *	Create proc dir entries for a I2O controller or I2O device.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_proc_create_entries(struct proc_dir_entry *dir,
+				   i2o_proc_entry * i2o_pe, void *data)
+{
+	struct proc_dir_entry *tmp;
 
-		ent->data = data;
-		ent->read_proc = pentry->read_proc;
-		ent->write_proc = pentry->write_proc;
-		if(pentry->fops_proc)
-			ent->proc_fops = pentry->fops_proc;
+	while (i2o_pe->name) {
+		tmp = create_proc_entry(i2o_pe->name, i2o_pe->mode, dir);
+		if (!tmp)
+			return -1;
 
-		ent->nlink = 1;
+		tmp->data = data;
+		tmp->proc_fops = i2o_pe->fops;
 
-		pentry++;
+		i2o_pe++;
 	}
 
 	return 0;
 }
 
-static void i2o_proc_remove_entries(i2o_proc_entry *pentry, 
-				    struct proc_dir_entry *parent)
-{
-	while(pentry->name != NULL)
-	{
-		remove_proc_entry(pentry->name, parent);
-		pentry++;
-	}
-}
-
-static int i2o_proc_add_controller(struct i2o_controller *pctrl, 
-				   struct proc_dir_entry *root )
+/**
+ *	i2o_proc_subdir_remove - Remove child entries from a proc entry
+ *	@dir: proc dir entry from which the childs should be removed
+ *
+ *	Iterate over each i2o proc entry under dir and remove it. If the child
+ *	also has entries, remove them too.
+ */
+static void i2o_proc_subdir_remove(struct proc_dir_entry *dir)
 {
-	struct proc_dir_entry *dir, *dir1;
-	struct i2o_device *dev;
-	char buff[10];
-
-	sprintf(buff, "iop%d", pctrl->unit);
-
-	dir = proc_mkdir(buff, root);
-	if(!dir)
-		return -1;
-
-	pctrl->proc_entry = dir;
-
-	i2o_proc_create_entries(pctrl, generic_iop_entries, dir);
-	
-	for(dev = pctrl->devices; dev; dev = dev->next)
-	{
-		sprintf(buff, "%0#5x", dev->lct_data.tid);
-
-		dir1 = proc_mkdir(buff, dir);
-		dev->proc_entry = dir1;
-
-		if(!dir1)
-			printk(KERN_INFO "i2o_proc: Could not allocate proc dir\n");
-
-		i2o_proc_add_device(dev, dir1);
+	struct proc_dir_entry *pe, *tmp;
+	pe = dir->subdir;
+	while (pe) {
+		tmp = pe->next;
+		i2o_proc_subdir_remove(pe);
+		remove_proc_entry(pe->name, dir);
+		pe = tmp;
 	}
+};
 
-	return 0;
-}
-
-void i2o_proc_new_dev(struct i2o_controller *c, struct i2o_device *d)
+/**
+ *	i2o_proc_device_add - Add an I2O device to the proc dir
+ *	@dir: proc dir entry to which the device should be added
+ *	@dev: I2O device which should be added
+ *
+ *	Add an I2O device to the proc dir entry dir and create the entries for
+ *	the device depending on the class of the I2O device.
+ */
+static void i2o_proc_device_add(struct proc_dir_entry *dir,
+				struct i2o_device *dev)
 {
 	char buff[10];
+	struct proc_dir_entry *devdir;
+	i2o_proc_entry *i2o_pe = NULL;
 
-#ifdef DRIVERDEBUG
-	printk(KERN_INFO "Adding new device to /proc/i2o/iop%d\n", c->unit);
-#endif
-	sprintf(buff, "%0#5x", d->lct_data.tid);
+	sprintf(buff, "%03x", dev->lct_data.tid);
 
-	d->proc_entry = proc_mkdir(buff, c->proc_entry);
+	pr_debug("Adding device /proc/i2o/iop%d/%s\n", dev->iop->unit, buff);
 
-	if(!d->proc_entry)
-	{
+	devdir = proc_mkdir(buff, dir);
+	if (!devdir) {
 		printk(KERN_WARNING "i2o: Could not allocate procdir!\n");
 		return;
 	}
 
-	i2o_proc_add_device(d, d->proc_entry);
-}
+	devdir->data = dev;
 
-void i2o_proc_add_device(struct i2o_device *dev, struct proc_dir_entry *dir)
-{	
-	i2o_proc_create_entries(dev, generic_dev_entries, dir);
+	i2o_proc_create_entries(devdir, generic_dev_entries, dev);
 
 	/* Inform core that we want updates about this device's status */
-	i2o_device_notify_on(dev, &i2o_proc_handler);
-	switch(dev->lct_data.class_id)
-	{
-		case I2O_CLASS_SCSI_PERIPHERAL:
-		case I2O_CLASS_RANDOM_BLOCK_STORAGE:
-			i2o_proc_create_entries(dev, rbs_dev_entries, dir);
-			break;
-		case I2O_CLASS_LAN:
-			i2o_proc_create_entries(dev, lan_entries, dir);
-			switch(dev->lct_data.sub_class)
-			{
-				case I2O_LAN_ETHERNET:
-					i2o_proc_create_entries(dev, lan_eth_entries, dir);
-					break;
-				case I2O_LAN_FDDI:
-					i2o_proc_create_entries(dev, lan_fddi_entries, dir);
-					break;
-				case I2O_LAN_TR:
-					i2o_proc_create_entries(dev, lan_tr_entries, dir);
-					break;
-				default:
-					break;
-			}
-			break;
-		default:
-			break;
+	switch (dev->lct_data.class_id) {
+	case I2O_CLASS_SCSI_PERIPHERAL:
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+		i2o_pe = rbs_dev_entries;
+		break;
+	default:
+		break;
 	}
+	if (i2o_pe)
+		i2o_proc_create_entries(devdir, i2o_pe, dev);
 }
 
-static void i2o_proc_remove_controller(struct i2o_controller *pctrl, 
-				       struct proc_dir_entry *parent)
+/**
+ *	i2o_proc_iop_add - Add an I2O controller to the i2o proc tree
+ *	@dir: parent proc dir entry
+ *	@c: I2O controller which should be added
+ *
+ *	Add the entries to the parent proc dir entry. Also each device is added
+ *	to the controllers proc dir entry.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_proc_iop_add(struct proc_dir_entry *dir,
+			    struct i2o_controller *c)
 {
-	char buff[10];
+	struct proc_dir_entry *iopdir;
 	struct i2o_device *dev;
+	char buff[10];
 
-	/* Remove unused device entries */
-	for(dev=pctrl->devices; dev; dev=dev->next)
-		i2o_proc_remove_device(dev);
+	snprintf(buff, 10, "iop%d", c->unit);
 
-	if(!atomic_read(&pctrl->proc_entry->count))
-	{
-		sprintf(buff, "iop%d", pctrl->unit);
+	pr_debug("Adding IOP /proc/i2o/%s\n", buff);
 
-		i2o_proc_remove_entries(generic_iop_entries, pctrl->proc_entry);
-		remove_proc_entry(buff, parent);
-		pctrl->proc_entry = NULL;
-	}
-}
+	iopdir = proc_mkdir(buff, dir);
+	if (!iopdir)
+		return -1;
 
-void i2o_proc_remove_device(struct i2o_device *dev)
-{
-	struct proc_dir_entry *de=dev->proc_entry;
-	char dev_id[10];
+	iopdir->data = c;
 
-	sprintf(dev_id, "%0#5x", dev->lct_data.tid);
+	i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c);
 
-	i2o_device_notify_off(dev, &i2o_proc_handler);
-	/* Would it be safe to remove _files_ even if they are in use? */
-	if((de) && (!atomic_read(&de->count)))
-	{
-		i2o_proc_remove_entries(generic_dev_entries, de);
-		switch(dev->lct_data.class_id)
-		{
-			case I2O_CLASS_SCSI_PERIPHERAL:
-			case I2O_CLASS_RANDOM_BLOCK_STORAGE:
-				i2o_proc_remove_entries(rbs_dev_entries, de);
-				break;
-			case I2O_CLASS_LAN:
-			{
-				i2o_proc_remove_entries(lan_entries, de);
-				switch(dev->lct_data.sub_class)
-				{
-				case I2O_LAN_ETHERNET:
-					i2o_proc_remove_entries(lan_eth_entries, de);
-					break;
-				case I2O_LAN_FDDI:
-					i2o_proc_remove_entries(lan_fddi_entries, de);
-					break;
-				case I2O_LAN_TR:
-					i2o_proc_remove_entries(lan_tr_entries, de);
-					break;
-				}
-			}
-		}
-		remove_proc_entry(dev_id, dev->controller->proc_entry);
-	}
+	list_for_each_entry(dev, &c->devices, list)
+	    i2o_proc_device_add(iopdir, dev);
+
+	return 0;
 }
-	
-void i2o_proc_dev_del(struct i2o_controller *c, struct i2o_device *d)
+
+/**
+ *	i2o_proc_iop_remove - Removes an I2O controller from the i2o proc tree
+ *	@dir: parent proc dir entry
+ *	@c: I2O controller which should be removed
+ *
+ *	Iterate over each i2o proc entry and search controller c. If it is found
+ *	remove it from the tree.
+ */
+static void i2o_proc_iop_remove(struct proc_dir_entry *dir,
+				struct i2o_controller *c)
 {
-#ifdef DRIVERDEBUG
-	printk(KERN_INFO "Deleting device %d from iop%d\n", 
-		d->lct_data.tid, c->unit);
-#endif
+	struct proc_dir_entry *pe, *tmp;
 
-	i2o_proc_remove_device(d);
+	pe = dir->subdir;
+	while (pe) {
+		tmp = pe->next;
+		if (pe->data == c) {
+			i2o_proc_subdir_remove(pe);
+			remove_proc_entry(pe->name, dir);
+		}
+		pr_debug("Removing IOP /proc/i2o/iop%d\n", c->unit);
+		pe = tmp;
+	}
 }
 
-static int create_i2o_procfs(void)
+/**
+ *	i2o_proc_fs_create - Create the i2o proc fs.
+ *
+ *	Iterate over each I2O controller and create the entries for it.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_proc_fs_create(void)
 {
-	struct i2o_controller *pctrl = NULL;
-	int i;
+	struct i2o_controller *c;
 
 	i2o_proc_dir_root = proc_mkdir("i2o", NULL);
-	if(!i2o_proc_dir_root)
+	if (!i2o_proc_dir_root)
 		return -1;
+
 	i2o_proc_dir_root->owner = THIS_MODULE;
 
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-		pctrl = i2o_find_controller(i);
-		if(pctrl)
-		{
-			i2o_proc_add_controller(pctrl, i2o_proc_dir_root);
-			i2o_unlock_controller(pctrl);
-		}
-	};
+	list_for_each_entry(c, &i2o_controllers, list)
+	    i2o_proc_iop_add(i2o_proc_dir_root, c);
 
 	return 0;
-}
+};
 
-static int __exit destroy_i2o_procfs(void)
+/**
+ *	i2o_proc_fs_destroy - Cleanup the all i2o proc entries
+ *
+ *	Iterate over each I2O controller and remove the entries for it.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __exit i2o_proc_fs_destroy(void)
 {
-	struct i2o_controller *pctrl = NULL;
-	int i;
+	struct i2o_controller *c;
 
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-		pctrl = i2o_find_controller(i);
-		if(pctrl)
-		{
-			i2o_proc_remove_controller(pctrl, i2o_proc_dir_root);
-			i2o_unlock_controller(pctrl);
-		}
-	}
+	list_for_each_entry(c, &i2o_controllers, list)
+	    i2o_proc_iop_remove(i2o_proc_dir_root, c);
 
-	if(!atomic_read(&i2o_proc_dir_root->count))
-		remove_proc_entry("i2o", NULL);
-	else
-		return -1;
+	remove_proc_entry("i2o", NULL);
 
 	return 0;
-}
+};
 
-int __init i2o_proc_init(void)
+/**
+ *	i2o_proc_init - Init function for procfs
+ *
+ *	Registers Proc OSM and creates procfs entries.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_proc_init(void)
 {
-	if (i2o_install_handler(&i2o_proc_handler) < 0)
-	{
-		printk(KERN_ERR "i2o_proc: Unable to install PROC handler.\n");
-		return 0;
-	}
+	int rc;
 
-	if(create_i2o_procfs())
-		return -EBUSY;
+	rc = i2o_driver_register(&i2o_proc_driver);
+	if (rc)
+		return rc;
+
+	rc = i2o_proc_fs_create();
+	if (rc) {
+		i2o_driver_unregister(&i2o_proc_driver);
+		return rc;
+	}
 
 	return 0;
-}
+};
+
+/**
+ *	i2o_proc_exit - Exit function for procfs
+ *
+ *	Unregisters Proc OSM and removes procfs entries.
+ */
+static void __exit i2o_proc_exit(void)
+{
+	i2o_driver_unregister(&i2o_proc_driver);
+	i2o_proc_fs_destroy();
+};
 
 MODULE_AUTHOR("Deepak Saxena");
 MODULE_DESCRIPTION("I2O procfs Handler");
 MODULE_LICENSE("GPL");
 
-static void __exit i2o_proc_exit(void)
-{
-	destroy_i2o_procfs();
-	i2o_remove_handler(&i2o_proc_handler);
-}
-
-#ifdef MODULE
 module_init(i2o_proc_init);
-#endif
 module_exit(i2o_proc_exit);
-
diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
--- a/drivers/message/i2o/i2o_scsi.c	2004-05-28 09:21:05 -07:00
+++ b/drivers/message/i2o/i2o_scsi.c	2004-08-19 09:24:16 -07:00
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -19,13 +19,13 @@
  *
  *	o	Each (bus,lun) is a logical device in I2O. We keep a map
  *		table. We spoof failed selection for unmapped units
- *	o	Request sense buffers can come back for free. 
+ *	o	Request sense buffers can come back for free.
  *	o	Scatter gather is a bit dynamic. We have to investigate at
  *		setup time.
  *	o	Some of our resources are dynamically shared. The i2o core
  *		needs a message reservation protocol to avoid swap v net
  *		deadlocking. We need to back off queue requests.
- *	
+ *
  *	In general the firmware wants to help. Where its help isn't performance
  *	useful we just ignore the aid. Its not worth the code in truth.
  *
@@ -40,7 +40,6 @@
  *	Fix the resource management problems.
  */
 
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -53,79 +52,229 @@
 #include <linux/proc_fs.h>
 #include <linux/prefetch.h>
 #include <linux/pci.h>
+#include <linux/blkdev.h>
+#include <linux/i2o.h>
+
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
-#include <linux/blkdev.h>
-#include <linux/i2o.h>
 
 #include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
-
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
 
 #define VERSION_STRING        "Version 0.1.2"
 
-//#define DRIVERDEBUG
+static struct i2o_driver i2o_scsi_driver;
 
-#ifdef DRIVERDEBUG
-#define dprintk(s, args...) printk(s, ## args)
-#else
-#define dprintk(s, args...)
-#endif
+static int i2o_scsi_max_id = 16;
+static int i2o_scsi_max_lun = 8;
+
+struct i2o_scsi_host {
+	struct Scsi_Host *scsi_host;	/* pointer to the SCSI host */
+	struct i2o_controller *iop;	/* pointer to the I2O controller */
+	struct i2o_device *channel[0];	/* channel->i2o_dev mapping table */
+};
+
+static struct scsi_host_template i2o_scsi_host_template;
 
 #define I2O_SCSI_CAN_QUEUE	4
-#define MAXHOSTS		32
 
-struct i2o_scsi_host
-{
-	struct i2o_controller *controller;
-	s16 task[16][8];		/* Allow 16 devices for now */
-	unsigned long tagclock[16][8];	/* Tag clock for queueing */
-	s16 bus_task;		/* The adapter TID */
+/* SCSI OSM class handling definition */
+static struct i2o_class_id i2o_scsi_class_id[] = {
+	{I2O_CLASS_SCSI_PERIPHERAL},
+	{I2O_CLASS_END}
 };
 
-static int scsi_context;
-static int lun_done;
-static int i2o_scsi_hosts;
-
-static u32 *retry[32];
-static struct i2o_controller *retry_ctrl[32];
-static struct timer_list retry_timer;
-static spinlock_t retry_lock = SPIN_LOCK_UNLOCKED;
-static int retry_ct = 0;
+static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
+{
+	struct i2o_scsi_host *i2o_shost;
+	struct i2o_device *i2o_dev;
+	struct Scsi_Host *scsi_host;
+	int max_channel = 0;
+	u8 type;
+	int i;
+	size_t size;
+	i2o_status_block *sb;
 
-static atomic_t queue_depth;
+	list_for_each_entry(i2o_dev, &c->devices, list)
+	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1))	/* SCSI bus */
+			max_channel++;
+	}
 
-/*
- *	SG Chain buffer support...
+	if (!max_channel) {
+		printk(KERN_WARNING "scsi-osm: no channels found on %s\n",
+		       c->name);
+		return ERR_PTR(-EFAULT);
+	}
+
+	size = max_channel * sizeof(struct i2o_device *)
+	    + sizeof(struct i2o_scsi_host);
+
+	scsi_host = scsi_host_alloc(&i2o_scsi_host_template, size);
+	if (!scsi_host) {
+		printk(KERN_WARNING "scsi-osm: Could not allocate SCSI host\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	scsi_host->max_channel = max_channel - 1;
+	scsi_host->max_id = i2o_scsi_max_id;
+	scsi_host->max_lun = i2o_scsi_max_lun;
+	scsi_host->this_id = c->unit;
+
+	sb = c->status_block.virt;
+
+	scsi_host->sg_tablesize = (sb->inbound_frame_size -
+				   sizeof(struct i2o_message) / 4 - 6) / 2;
+
+	i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata;
+	i2o_shost->scsi_host = scsi_host;
+	i2o_shost->iop = c;
+
+	i = 0;
+	list_for_each_entry(i2o_dev, &c->devices, list)
+	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1))	/* only SCSI bus */
+			i2o_shost->channel[i++] = i2o_dev;
+
+		if (i >= max_channel)
+			break;
+	}
+
+	return i2o_shost;
+};
+
+/**
+ *	i2o_scsi_get_host - Get an I2O SCSI host
+ *	@c: I2O controller to for which to get the SCSI host
+ *
+ *	If the I2O controller already exists as SCSI host, the SCSI host
+ *	is returned, otherwise the I2O controller is added to the SCSI
+ *	core.
+ *
+ *	Returns pointer to the I2O SCSI host on success or NULL on failure.
  */
+static struct i2o_scsi_host *i2o_scsi_get_host(struct i2o_controller *c)
+{
+	return c->driver_data[i2o_scsi_driver.context];
+};
 
-#define SG_MAX_FRAGS		64
+/**
+ *	i2o_scsi_remove - Remove I2O device from SCSI core
+ *	@dev: device which should be removed
+ *
+ *	Removes the I2O device from the SCSI core again.
+ *
+ *	Returns 0 on success.
+ */
+static int i2o_scsi_remove(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_scsi_host *i2o_shost;
+	struct scsi_device *scsi_dev;
 
-/*
- *	FIXME: we should allocate one of these per bus we find as we
- *	locate them not in a lump at boot.
+	i2o_shost = i2o_scsi_get_host(c);
+
+	shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
+	    if (scsi_dev->hostdata == i2o_dev) {
+		scsi_remove_device(scsi_dev);
+		scsi_device_put(scsi_dev);
+		break;
+	}
+
+	return 0;
+};
+
+/**
+ *	i2o_scsi_probe - verify if dev is a I2O SCSI device and install it
+ *	@dev: device to verify if it is a I2O SCSI device
+ *
+ *	Retrieve channel, id and lun for I2O device. If everthing goes well
+ *	register the I2O device as SCSI device on the I2O SCSI controller.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
- 
-typedef struct _chain_buf
+static int i2o_scsi_probe(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_scsi_host *i2o_shost;
+	struct Scsi_Host *scsi_host;
+	struct i2o_device *parent;
+	struct scsi_device *scsi_dev;
+	u32 id;
+	u64 lun;
+	int channel = -1;
+	int i;
+
+	i2o_shost = i2o_scsi_get_host(c);
+	if (!i2o_shost)
+		return -EFAULT;
+
+	scsi_host = i2o_shost->scsi_host;
+
+	if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0)
+		return -EFAULT;
+
+	if (id >= scsi_host->max_id) {
+		printk(KERN_WARNING "scsi-osm: SCSI device id (%d) >= max_id "
+		       "of I2O host (%d)", id, scsi_host->max_id);
+		return -EFAULT;
+	}
+
+	if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0)
+		return -EFAULT;
+	if (lun >= scsi_host->max_lun) {
+		printk(KERN_WARNING "scsi-osm: SCSI device id (%d) >= max_lun "
+		       "of I2O host (%d)", (unsigned int)lun,
+		       scsi_host->max_lun);
+		return -EFAULT;
+	}
+
+	parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
+	if (!parent) {
+		printk(KERN_WARNING "scsi-osm: can not find parent of device "
+		       "%03x\n", i2o_dev->lct_data.tid);
+		return -EFAULT;
+	}
+
+	for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
+		if (i2o_shost->channel[i] == parent)
+			channel = i;
+
+	if (channel == -1) {
+		printk(KERN_WARNING "scsi-osm: can not find channel of device "
+		       "%03x\n", i2o_dev->lct_data.tid);
+		return -EFAULT;
+	}
+
+	scsi_dev =
+	    __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
+
+	if (!scsi_dev) {
+		printk(KERN_WARNING "scsi-osm: can not add SCSI device "
+		       "%03x\n", i2o_dev->lct_data.tid);
+		return -EFAULT;
+	}
+
+	pr_debug("Added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n",
+		 i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
+
+	return 0;
+};
+
+static const char *i2o_scsi_info(struct Scsi_Host *SChost)
 {
-	u32 sg_flags_cnt[SG_MAX_FRAGS];
-	u32 sg_buf[SG_MAX_FRAGS];
-} chain_buf;
-
-#define SG_CHAIN_BUF_SZ sizeof(chain_buf)
-
-#define SG_MAX_BUFS		(i2o_num_controllers * I2O_SCSI_CAN_QUEUE)
-#define SG_CHAIN_POOL_SZ	(SG_MAX_BUFS * SG_CHAIN_BUF_SZ)
-
-static int max_sg_len = 0;
-static chain_buf *sg_chain_pool = NULL;
-static int sg_chain_tag = 0;
-static int sg_max_frags = SG_MAX_FRAGS;
+	struct i2o_scsi_host *hostdata;
+	hostdata = (struct i2o_scsi_host *)SChost->hostdata;
+	return hostdata->iop->name;
+}
 
+#if 0
 /**
  *	i2o_retry_run		-	retry on timeout
  *	@f: unused
@@ -136,16 +285,16 @@
  *	and its default handler should be this in the core, and this
  *	call a 2nd "I give up" handler in the OSM ?
  */
- 
+
 static void i2o_retry_run(unsigned long f)
 {
 	int i;
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&retry_lock, flags);
-	for(i=0;i<retry_ct;i++)
+	for (i = 0; i < retry_ct; i++)
 		i2o_post_message(retry_ctrl[i], virt_to_bus(retry[i]));
-	retry_ct=0;
+	retry_ct = 0;
 	spin_unlock_irqrestore(&retry_lock, flags);
 }
 
@@ -155,860 +304,507 @@
  *	Turn each of the pending commands into a NOP and post it back
  *	to the controller to clear it.
  */
- 
+
 static void flush_pending(void)
 {
 	int i;
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&retry_lock, flags);
-	for(i=0;i<retry_ct;i++)
-	{
-		retry[i][0]&=~0xFFFFFF;
-		retry[i][0]|=I2O_CMD_UTIL_NOP<<24;
-		i2o_post_message(retry_ctrl[i],virt_to_bus(retry[i]));
+	for (i = 0; i < retry_ct; i++) {
+		retry[i][0] &= ~0xFFFFFF;
+		retry[i][0] |= I2O_CMD_UTIL_NOP << 24;
+		i2o_post_message(retry_ctrl[i], virt_to_bus(retry[i]));
 	}
-	retry_ct=0;
+	retry_ct = 0;
 	spin_unlock_irqrestore(&retry_lock, flags);
 }
+#endif
 
 /**
- *	i2o_scsi_reply		-	scsi message reply processor
- *	@h: our i2o handler
+ *	i2o_scsi_reply - SCSI OSM message reply handler
  *	@c: controller issuing the reply
- *	@msg: the message from the controller (mapped)
+ *	@m: message id for flushing
+ *	@msg: the message from the controller
  *
  *	Process reply messages (interrupts in normal scsi controller think).
  *	We can get a variety of messages to process. The normal path is
  *	scsi command completions. We must also deal with IOP failures,
  *	the reply to a bus reset and the reply to a LUN query.
  *
- *	Locks: the queue lock is taken to call the completion handler
+ *	Returns 0 on success and if the reply should not be flushed or > 0
+ *	on success and if the reply should be flushed. Returns negative error
+ *	code on failure and if the reply should be flushed.
  */
-
-static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
+static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
+			  struct i2o_message *msg)
 {
-	struct scsi_cmnd *current_command;
-	spinlock_t *lock;
-	u32 *m = (u32 *)msg;
-	u8 as,ds,st;
-	unsigned long flags;
+	struct scsi_cmnd *cmd;
+	struct device *dev;
+	u8 as, ds, st;
+
+	cmd = i2o_cntxt_list_get(c, readl(&msg->u.s.tcntxt));
+
+	if (msg->u.head[0] & (1 << 13)) {
+		struct i2o_message *pmsg;	/* preserved message */
+		u32 pm;
+
+		pm = readl(&msg->body[3]);
+
+		pmsg = c->in_queue.virt + pm;
 
-	if(m[0] & (1<<13))
-	{
 		printk("IOP fail.\n");
 		printk("From %d To %d Cmd %d.\n",
-			(m[1]>>12)&0xFFF,
-			m[1]&0xFFF,
-			m[1]>>24);
-		printk("Failure Code %d.\n", m[4]>>24);
-		if(m[4]&(1<<16))
+		       (msg->u.head[1] >> 12) & 0xFFF,
+		       msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24);
+		printk("Failure Code %d.\n", msg->body[0] >> 24);
+		if (msg->body[0] & (1 << 16))
 			printk("Format error.\n");
-		if(m[4]&(1<<17))
+		if (msg->body[0] & (1 << 17))
 			printk("Path error.\n");
-		if(m[4]&(1<<18))
+		if (msg->body[0] & (1 << 18))
 			printk("Path State.\n");
-		if(m[4]&(1<<18))
+		if (msg->body[0] & (1 << 18))
 			printk("Congestion.\n");
-		
-		m=(u32 *)bus_to_virt(m[7]);
-		printk("Failing message is %p.\n", m);
-		
-		/* This isnt a fast path .. */
-		spin_lock_irqsave(&retry_lock, flags);
-		
-		if((m[4]&(1<<18)) && retry_ct < 32)
-		{
-			retry_ctrl[retry_ct]=c;
-			retry[retry_ct]=m;
-			if(!retry_ct++)
-			{
-				retry_timer.expires=jiffies+1;
-				add_timer(&retry_timer);
-			}
-			spin_unlock_irqrestore(&retry_lock, flags);
-		}
-		else
-		{
-			spin_unlock_irqrestore(&retry_lock, flags);
-			/* Create a scsi error for this */
-			current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c);
-			if(!current_command)
-				return;
-
-			lock = current_command->device->host->host_lock;
-			printk("Aborted %ld\n", current_command->serial_number);
-
-			spin_lock_irqsave(lock, flags);
-			current_command->result = DID_ERROR << 16;
-			current_command->scsi_done(current_command);
-			spin_unlock_irqrestore(lock, flags);
-			
-			/* Now flush the message by making it a NOP */
-			m[0]&=0x00FFFFFF;
-			m[0]|=(I2O_CMD_UTIL_NOP)<<24;
-			i2o_post_message(c,virt_to_bus(m));
-		}
-		return;
+
+		printk("Failing message is %p.\n", pmsg);
+
+		cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
+		if (!cmd)
+			return 1;
+
+		printk("Aborted %ld\n", cmd->serial_number);
+		cmd->result = DID_ERROR << 16;
+		cmd->scsi_done(cmd);
+
+		/* Now flush the message by making it a NOP */
+		i2o_msg_nop(c, pm);
+
+		return 1;
 	}
-	
-	prefetchw(&queue_depth);
-		
-	
+
 	/*
-	 *	Low byte is device status, next is adapter status,
-	 *	(then one byte reserved), then request status.
+	 *      Low byte is device status, next is adapter status,
+	 *      (then one byte reserved), then request status.
 	 */
-	ds=(u8)le32_to_cpu(m[4]);
-	as=(u8)le32_to_cpu(m[4]>>8);
-	st=(u8)le32_to_cpu(m[4]>>24);
-	
-	dprintk(KERN_INFO "i2o got a scsi reply %08X: ", m[0]);
-	dprintk(KERN_INFO "m[2]=%08X: ", m[2]);
-	dprintk(KERN_INFO "m[4]=%08X\n", m[4]);
- 
-	if(m[2]&0x80000000)
-	{
-		if(m[2]&0x40000000)
-		{
-			dprintk(KERN_INFO "Event.\n");
-			lun_done=1;
-			return;
-		}
-		printk(KERN_INFO "i2o_scsi: bus reset completed.\n");
-		return;
-	}
+	ds = (u8) readl(&msg->body[0]);
+	as = (u8) (readl(&msg->body[0]) >> 8);
+	st = (u8) (readl(&msg->body[0]) >> 24);
 
-	current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c);
-	
 	/*
-	 *	Is this a control request coming back - eg an abort ?
+	 *      Is this a control request coming back - eg an abort ?
 	 */
-	 
-	atomic_dec(&queue_depth);
 
-	if(current_command==NULL)
-	{
-		if(st)
-			dprintk(KERN_WARNING "SCSI abort: %08X", m[4]);
-		dprintk(KERN_INFO "SCSI abort completed.\n");
-		return;
+	if (!cmd) {
+		if (st)
+			printk(KERN_WARNING "SCSI abort: %08X",
+			       readl(&msg->body[0]));
+		printk(KERN_INFO "SCSI abort completed.\n");
+		return -EFAULT;
 	}
-	
-	dprintk(KERN_INFO "Completed %ld\n", current_command->serial_number);
-	
-	if(st == 0x06)
-	{
-		if(le32_to_cpu(m[5]) < current_command->underflow)
-		{
-			int i;
-			printk(KERN_ERR "SCSI: underflow 0x%08X 0x%08X\n",
-				le32_to_cpu(m[5]), current_command->underflow);
-			printk("Cmd: ");
-			for(i=0;i<15;i++)
-				printk("%02X ", current_command->cmnd[i]);
-			printk(".\n");
-		}
-		else st=0;
-	}
-	
-	if(st)
-	{
-		/* An error has occurred */
 
-		dprintk(KERN_WARNING "SCSI error %08X", m[4]);
-			
-		if (as == 0x0E) 
-			/* SCSI Reset */
-			current_command->result = DID_RESET << 16;
-		else if (as == 0x0F)
-			current_command->result = DID_PARITY << 16;
-		else
-			current_command->result = DID_ERROR << 16;
-	}
-	else
-		/*
-		 *	It worked maybe ?
-		 */		
-		current_command->result = DID_OK << 16 | ds;
-
-	if (current_command->use_sg) {
-		pci_unmap_sg(c->pdev,
-			(struct scatterlist *)current_command->buffer,
-			current_command->use_sg,
-			current_command->sc_data_direction);
-	} else if (current_command->request_bufflen) {
-		pci_unmap_single(c->pdev,
-			(dma_addr_t)((long)current_command->SCp.ptr),
-			current_command->request_bufflen,
-			current_command->sc_data_direction);
-	}
-
-	lock = current_command->device->host->host_lock;
-	spin_lock_irqsave(lock, flags);
-	current_command->scsi_done(current_command);
-	spin_unlock_irqrestore(lock, flags);
-	return;
-}
+	pr_debug("Completed %ld\n", cmd->serial_number);
 
-struct i2o_handler i2o_scsi_handler = {
-	.reply	= i2o_scsi_reply,
-	.name	= "I2O SCSI OSM",
-	.class	= I2O_CLASS_SCSI_PERIPHERAL,
-};
+	if (st) {
+		u32 count, error;
+		/* An error has occurred */
 
-/**
- *	i2o_find_lun		-	report the lun of an i2o device
- *	@c: i2o controller owning the device
- *	@d: i2o disk device
- *	@target: filled in with target id
- *	@lun: filled in with target lun
- *
- *	Query an I2O device to find out its SCSI lun and target numbering. We
- *	don't currently handle some of the fancy SCSI-3 stuff although our
- *	querying is sufficient to do so.
- */
- 
-static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *target, int *lun)
-{
-	u8 reply[8];
-	
-	if(i2o_query_scalar(c, d->lct_data.tid, 0, 3, reply, 4)<0)
-		return -1;
-		
-	*target=reply[0];
-	
-	if(i2o_query_scalar(c, d->lct_data.tid, 0, 4, reply, 8)<0)
-		return -1;
+		switch (st) {
+		case 0x06:
+			count = readl(&msg->body[1]);
+			if (count < cmd->underflow) {
+				int i;
+				printk(KERN_ERR "SCSI: underflow 0x%08X 0x%08X"
+				       "\n", count, cmd->underflow);
+				printk("Cmd: ");
+				for (i = 0; i < 15; i++)
+					printk("%02X ", cmd->cmnd[i]);
+				printk(".\n");
+				cmd->result = (DID_ERROR << 16);
+			}
+			break;
 
-	*lun=reply[1];
+		default:
+			error = readl(&msg->body[0]);
 
-	dprintk(KERN_INFO "SCSI (%d,%d)\n", *target, *lun);
-	return 0;
-}
+			printk(KERN_ERR "scsi-osm: SCSI error %08x\n", error);
 
-/**
- *	i2o_scsi_init		-	initialize an i2o device for scsi
- *	@c: i2o controller owning the device
- *	@d: scsi controller
- *	@shpnt: scsi device we wish it to become
- *
- *	Enumerate the scsi peripheral/fibre channel peripheral class
- *	devices that are children of the controller. From that we build
- *	a translation map for the command queue code. Since I2O works on
- *	its own tid's we effectively have to think backwards to get what
- *	the midlayer wants
- */
- 
-static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_Host *shpnt)
-{
-	struct i2o_device *unit;
-	struct i2o_scsi_host *h =(struct i2o_scsi_host *)shpnt->hostdata;
-	int lun;
-	int target;
-	
-	h->controller=c;
-	h->bus_task=d->lct_data.tid;
-	
-	for(target=0;target<16;target++)
-		for(lun=0;lun<8;lun++)
-			h->task[target][lun] = -1;
-			
-	for(unit=c->devices;unit!=NULL;unit=unit->next)
-	{
-		dprintk(KERN_INFO "Class %03X, parent %d, want %d.\n",
-			unit->lct_data.class_id, unit->lct_data.parent_tid, d->lct_data.tid);
-			
-		/* Only look at scsi and fc devices */
-		if (    (unit->lct_data.class_id != I2O_CLASS_SCSI_PERIPHERAL)
-		     && (unit->lct_data.class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL)
-		   )
-			continue;
-
-		/* On our bus ? */
-		dprintk(KERN_INFO "Found a disk (%d).\n", unit->lct_data.tid);
-		if ((unit->lct_data.parent_tid == d->lct_data.tid)
-		     || (unit->lct_data.parent_tid == d->lct_data.parent_tid)
-		   )
-		{
-			u16 limit;
-			dprintk(KERN_INFO "Its ours.\n");
-			if(i2o_find_lun(c, unit, &target, &lun)==-1)
-			{
-				printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", unit->lct_data.tid);
-				continue;
+			if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) {
+				int i;
+				u32 len = sizeof(cmd->sense_buffer);
+				len = (len > 40) ? 40 : len;
+				// Copy over the sense data
+				memcpy(cmd->sense_buffer, (void *)&msg->body[3],
+				       len);
+				for (i = 0; i <= len; i++)
+					printk(KERN_INFO "%02x\n",
+					       cmd->sense_buffer[i]);
+				if (cmd->sense_buffer[0] == 0x70
+				    && cmd->sense_buffer[2] == DATA_PROTECT) {
+					/* This is to handle an array failed */
+					cmd->result = (DID_TIME_OUT << 16);
+					printk(KERN_WARNING "%s: SCSI Data "
+					       "Protect-Device (%d,%d,%d) "
+					       "hba_status=0x%x, dev_status="
+					       "0x%x, cmd=0x%x\n", c->name,
+					       (u32) cmd->device->channel,
+					       (u32) cmd->device->id,
+					       (u32) cmd->device->lun,
+					       (error >> 8) & 0xff,
+					       error & 0xff, cmd->cmnd[0]);
+				} else
+					cmd->result = (DID_ERROR << 16);
+
+				break;
 			}
-			dprintk(KERN_INFO "Found disk %d %d.\n", target, lun);
-			h->task[target][lun]=unit->lct_data.tid;
-			h->tagclock[target][lun]=jiffies;
-
-			/* Get the max fragments/request */
-			i2o_query_scalar(c, d->lct_data.tid, 0xF103, 3, &limit, 2);
-			
-			/* sanity */
-			if ( limit == 0 )
-			{
-				printk(KERN_WARNING "i2o_scsi: Ignoring unreasonable SG limit of 0 from IOP!\n");
-				limit = 1;
+
+			switch (as) {
+			case 0x0E:
+				/* SCSI Reset */
+				cmd->result = DID_RESET << 16;
+				break;
+
+			case 0x0F:
+				cmd->result = DID_PARITY << 16;
+				break;
+
+			default:
+				cmd->result = DID_ERROR << 16;
+				break;
 			}
-			
-			shpnt->sg_tablesize = limit;
 
-			dprintk(KERN_INFO "i2o_scsi: set scatter-gather to %d.\n",
-				shpnt->sg_tablesize);
+			break;
 		}
-	}		
-}
 
-/**
- *	i2o_scsi_detect		-	probe for I2O scsi devices
- *	@tpnt: scsi layer template
- *
- *	I2O is a little odd here. The I2O core already knows what the
- *	devices are. It also knows them by disk and tape as well as
- *	by controller. We register each I2O scsi class object as a
- *	scsi controller and then let the enumeration fake up the rest
- */
- 
-static int i2o_scsi_detect(struct scsi_host_template * tpnt)
-{
-	struct Scsi_Host *shpnt = NULL;
-	int i;
-	int count;
+		cmd->scsi_done(cmd);
+		return 1;
+	}
 
-	printk(KERN_INFO "i2o_scsi.c: %s\n", VERSION_STRING);
+	cmd->result = DID_OK << 16 | ds;
 
-	if(i2o_install_handler(&i2o_scsi_handler)<0)
-	{
-		printk(KERN_ERR "i2o_scsi: Unable to install OSM handler.\n");
-		return 0;
-	}
-	scsi_context = i2o_scsi_handler.context;
-	
-	if((sg_chain_pool = kmalloc(SG_CHAIN_POOL_SZ, GFP_KERNEL)) == NULL)
-	{
-		printk(KERN_INFO "i2o_scsi: Unable to alloc %d byte SG chain buffer pool.\n", SG_CHAIN_POOL_SZ);
-		printk(KERN_INFO "i2o_scsi: SG chaining DISABLED!\n");
-		sg_max_frags = 11;
-	}
-	else
-	{
-		printk(KERN_INFO "  chain_pool: %d bytes @ %p\n", SG_CHAIN_POOL_SZ, sg_chain_pool);
-		printk(KERN_INFO "  (%d byte buffers X %d can_queue X %d i2o controllers)\n",
-				SG_CHAIN_BUF_SZ, I2O_SCSI_CAN_QUEUE, i2o_num_controllers);
-		sg_max_frags = SG_MAX_FRAGS;    // 64
-	}
-	
-	init_timer(&retry_timer);
-	retry_timer.data = 0UL;
-	retry_timer.function = i2o_retry_run;
-	
-//	printk("SCSI OSM at %d.\n", scsi_context);
-
-	for (count = 0, i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-		struct i2o_controller *c=i2o_find_controller(i);
-		struct i2o_device *d;
-		/*
-		 *	This controller doesn't exist.
-		 */
-		
-		if(c==NULL)
-			continue;
-			
-		/*
-		 *	Fixme - we need some altered device locking. This
-		 *	is racing with device addition in theory. Easy to fix.
-		 */
-		
-		for(d=c->devices;d!=NULL;d=d->next)
-		{
-			/*
-			 *	bus_adapter, SCSI (obsolete), or FibreChannel busses only
-			 */
-			if(    (d->lct_data.class_id!=I2O_CLASS_BUS_ADAPTER_PORT)	// bus_adapter
-//			    && (d->lct_data.class_id!=I2O_CLASS_FIBRE_CHANNEL_PORT)	// FC_PORT
-			  )
-				continue;
-		
-			shpnt = scsi_register(tpnt, sizeof(struct i2o_scsi_host));
-			if(shpnt==NULL)
-				continue;
-			shpnt->unique_id = (u32)d;
-			shpnt->io_port = 0;
-			shpnt->n_io_port = 0;
-			shpnt->irq = 0;
-			shpnt->this_id = /* Good question */15;
-			i2o_scsi_init(c, d, shpnt);
-			count++;
-		}
-	}
-	i2o_scsi_hosts = count;
-	
-	if(count==0)
-	{
-		if(sg_chain_pool!=NULL)
-		{
-			kfree(sg_chain_pool);
-			sg_chain_pool = NULL;
-		}
-		flush_pending();
-		del_timer(&retry_timer);
-		i2o_remove_handler(&i2o_scsi_handler);
+	cmd->scsi_done(cmd);
+
+	dev = &c->pdev->dev;
+	if (cmd->use_sg)
+		dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer,
+			     cmd->use_sg, cmd->sc_data_direction);
+	else if (cmd->request_bufflen)
+		dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr),
+				 cmd->request_bufflen, cmd->sc_data_direction);
+
+	return 1;
+};
+
+/**
+ *	i2o_scsi_notify_controller_add - Retrieve notifications of added
+ *					 controllers
+ *	@c: the controller which was added
+ *
+ *	If a I2O controller is added, we catch the notification to add a
+ *	corresponding Scsi_Host.
+ */
+void i2o_scsi_notify_controller_add(struct i2o_controller *c)
+{
+	struct i2o_scsi_host *i2o_shost;
+	int rc;
+
+	i2o_shost = i2o_scsi_host_alloc(c);
+	if (IS_ERR(i2o_shost)) {
+		printk(KERN_ERR "scsi-osm: Could not initialize"
+		       " SCSI host\n");
+		return;
 	}
-	
-	return count;
-}
 
-static int i2o_scsi_release(struct Scsi_Host *host)
-{
-	if(--i2o_scsi_hosts==0)
-	{
-		if(sg_chain_pool!=NULL)
-		{
-			kfree(sg_chain_pool);
-			sg_chain_pool = NULL;
-		}
-		flush_pending();
-		del_timer(&retry_timer);
-		i2o_remove_handler(&i2o_scsi_handler);
+	rc = scsi_add_host(i2o_shost->scsi_host, &c->device);
+	if (rc) {
+		printk(KERN_ERR "scsi-osm: Could not add SCSI "
+		       "host\n");
+		scsi_host_put(i2o_shost->scsi_host);
+		return;
 	}
 
-	scsi_unregister(host);
+	c->driver_data[i2o_scsi_driver.context] = i2o_shost;
 
-	return 0;
-}
+	pr_debug("new I2O SCSI host added\n");
+};
 
+/**
+ *	i2o_scsi_notify_controller_remove - Retrieve notifications of removed
+ *					    controllers
+ *	@c: the controller which was removed
+ *
+ *	If a I2O controller is removed, we catch the notification to remove the
+ *	corresponding Scsi_Host.
+ */
+void i2o_scsi_notify_controller_remove(struct i2o_controller *c)
+{
+	struct i2o_scsi_host *i2o_shost;
+	i2o_shost = i2o_scsi_get_host(c);
+	if (!i2o_shost)
+		return;
 
-static const char *i2o_scsi_info(struct Scsi_Host *SChost)
-{
-	struct i2o_scsi_host *hostdata;
-	hostdata = (struct i2o_scsi_host *)SChost->hostdata;
-	return(&hostdata->controller->name[0]);
-}
+	c->driver_data[i2o_scsi_driver.context] = NULL;
+
+	scsi_remove_host(i2o_shost->scsi_host);
+	scsi_host_put(i2o_shost->scsi_host);
+	pr_debug("I2O SCSI host removed\n");
+};
+
+/* SCSI OSM driver struct */
+static struct i2o_driver i2o_scsi_driver = {
+	.name = "scsi-osm",
+	.reply = i2o_scsi_reply,
+	.classes = i2o_scsi_class_id,
+	.notify_controller_add = i2o_scsi_notify_controller_add,
+	.notify_controller_remove = i2o_scsi_notify_controller_remove,
+	.driver = {
+		   .probe = i2o_scsi_probe,
+		   .remove = i2o_scsi_remove,
+		   },
+};
 
 /**
- *	i2o_scsi_queuecommand	-	queue a SCSI command
+ *	i2o_scsi_queuecommand - queue a SCSI command
  *	@SCpnt: scsi command pointer
  *	@done: callback for completion
  *
- *	Issue a scsi comamnd asynchronously. Return 0 on success or 1 if
- *	we hit an error (normally message queue congestion). The only 
+ *	Issue a scsi command asynchronously. Return 0 on success or 1 if
+ *	we hit an error (normally message queue congestion). The only
  *	minor complication here is that I2O deals with the device addressing
  *	so we have to map the bus/dev/lun back to an I2O handle as well
- *	as faking absent devices ourself. 
+ *	as faking absent devices ourself.
  *
  *	Locks: takes the controller lock on error path only
  */
- 
+
 static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 				 void (*done) (struct scsi_cmnd *))
 {
-	int i;
-	int tid;
 	struct i2o_controller *c;
-	struct scsi_cmnd *current_command;
 	struct Scsi_Host *host;
-	struct i2o_scsi_host *hostdata;
-	u32 *msg, *mptr;
+	struct i2o_device *i2o_dev;
+	struct device *dev;
+	int tid;
+	struct i2o_message *msg;
 	u32 m;
-	u32 *lenptr;
-	int direction;
-	int scsidir;
-	u32 len;
-	u32 reqlen;
-	u32 tag;
-	unsigned long flags;
-	
-	static int max_qd = 1;
-	
+	u32 scsi_flags, sg_flags;
+	u32 *mptr, *lenptr;
+	u32 len, reqlen;
+	int i;
+
 	/*
-	 *	Do the incoming paperwork
+	 *      Do the incoming paperwork
 	 */
-	 
+
+	i2o_dev = SCpnt->device->hostdata;
 	host = SCpnt->device->host;
-	hostdata = (struct i2o_scsi_host *)host->hostdata;
-	 
-	c = hostdata->controller;
-	prefetch(c);
-	prefetchw(&queue_depth);
+	c = i2o_dev->iop;
+	dev = &c->pdev->dev;
 
 	SCpnt->scsi_done = done;
-	
-	if(SCpnt->device->id > 15)
-	{
-		printk(KERN_ERR "i2o_scsi: Wild target %d.\n", SCpnt->device->id);
-		return -1;
-	}
-	
-	tid = hostdata->task[SCpnt->device->id][SCpnt->device->lun];
-	
-	dprintk(KERN_INFO "qcmd: Tid = %d\n", tid);
-	
-	current_command = SCpnt;		/* set current command                */
-	current_command->scsi_done = done;	/* set ptr to done function           */
-
-	/* We don't have such a device. Pretend we did the command 
-	   and that selection timed out */
-	
-	if(tid == -1)
-	{
+
+	if (unlikely(!i2o_dev)) {
+		printk(KERN_WARNING "scsi-osm: no I2O device in request\n");
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		return 0;
 	}
-	
-	dprintk(KERN_INFO "Real scsi messages.\n");
+
+	tid = i2o_dev->lct_data.tid;
+
+	pr_debug("qcmd: Tid = %03x\n", tid);
+	pr_debug("Real scsi messages.\n");
 
 	/*
-	 *	Obtain an I2O message. If there are none free then 
-	 *	throw it back to the scsi layer
-	 */	
-	 
-	m = le32_to_cpu(I2O_POST_READ32(c));
-	if(m==0xFFFFFFFF)
-		return 1;
+	 *      Obtain an I2O message. If there are none free then
+	 *      throw it back to the scsi layer
+	 */
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return SCSI_MLQUEUE_HOST_BUSY;
 
-	msg = (u32 *)(c->msg_virt + m);
-	
 	/*
-	 *	Put together a scsi execscb message
+	 *      Put together a scsi execscb message
 	 */
-	
+
 	len = SCpnt->request_bufflen;
-	direction = 0x00000000;			// SGL IN  (osm<--iop)
-	
-	if (SCpnt->sc_data_direction == DMA_NONE) {
-		scsidir = 0x00000000;			// DATA NO XFER
-	} else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
-		direction = 0x04000000;	// SGL OUT  (osm-->iop)
-		scsidir = 0x80000000;	// DATA OUT (iop-->dev)
-	} else if(SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
-		scsidir = 0x40000000;	// DATA IN  (iop<--dev)
-	} else {
+
+	switch (SCpnt->sc_data_direction) {
+	case PCI_DMA_NONE:
+		scsi_flags = 0x00000000;	// DATA NO XFER
+		sg_flags = 0x00000000;
+		break;
+
+	case PCI_DMA_TODEVICE:
+		scsi_flags = 0x80000000;	// DATA OUT (iop-->dev)
+		sg_flags = 0x14000000;
+		break;
+
+	case PCI_DMA_FROMDEVICE:
+		scsi_flags = 0x40000000;	// DATA IN  (iop<--dev)
+		sg_flags = 0x10000000;
+		break;
+
+	default:
 		/* Unknown - kill the command */
 		SCpnt->result = DID_NO_CONNECT << 16;
-		
-		/* We must lock the request queue while completing */
-		spin_lock_irqsave(host->host_lock, flags);
 		done(SCpnt);
-		spin_unlock_irqrestore(host->host_lock, flags);
 		return 0;
 	}
 
-	
-	i2o_raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]);
-	i2o_raw_writel(scsi_context, &msg[2]);	/* So the I2O layer passes to us */
-	i2o_raw_writel(i2o_context_list_add(SCpnt, c), &msg[3]);	/* We want the SCSI control block back */
+	writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]);
+	writel(i2o_scsi_driver.context, &msg->u.s.icntxt);
+
+	/* We want the SCSI control block back */
+	writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt);
 
 	/* LSI_920_PCI_QUIRK
 	 *
-	 *	Intermittant observations of msg frame word data corruption
-	 *	observed on msg[4] after:
-	 *	  WRITE, READ-MODIFY-WRITE
-	 *	operations.  19990606 -sralston
+	 *      Intermittant observations of msg frame word data corruption
+	 *      observed on msg[4] after:
+	 *        WRITE, READ-MODIFY-WRITE
+	 *      operations.  19990606 -sralston
 	 *
-	 *	(Hence we build this word via tag. Its good practice anyway
-	 *	 we don't want fetches over PCI needlessly)
+	 *      (Hence we build this word via tag. Its good practice anyway
+	 *       we don't want fetches over PCI needlessly)
 	 */
 
-	tag=0;
-	
+	/* Attach tags to the devices */
 	/*
-	 *	Attach tags to the devices
-	 */	
-	if(SCpnt->device->tagged_supported)
-	{
-		/*
-		 *	Some drives are too stupid to handle fairness issues
-		 *	with tagged queueing. We throw in the odd ordered
-		 *	tag to stop them starving themselves.
-		 */
-		if((jiffies - hostdata->tagclock[SCpnt->device->id][SCpnt->device->lun]) > (5*HZ))
-		{
-			tag=0x01800000;		/* ORDERED! */
-			hostdata->tagclock[SCpnt->device->id][SCpnt->device->lun]=jiffies;
-		}
-		else
-		{
-			/* Hmmm...  I always see value of 0 here,
-			 *  of which {HEAD_OF, ORDERED, SIMPLE} are NOT!  -sralston
-			 */
-			if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
-				tag=0x01000000;
-			else if(SCpnt->tag == ORDERED_QUEUE_TAG)
-				tag=0x01800000;
-		}
-	}
+	   if(SCpnt->device->tagged_supported) {
+	   if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
+	   scsi_flags |= 0x01000000;
+	   else if(SCpnt->tag == ORDERED_QUEUE_TAG)
+	   scsi_flags |= 0x01800000;
+	   }
+	 */
 
 	/* Direction, disconnect ok, tag, CDBLen */
-	i2o_raw_writel(scsidir|0x20000000|SCpnt->cmd_len|tag, &msg[4]);
+	writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]);
 
-	mptr=msg+5;
+	mptr = &msg->body[1];
 
-	/* 
-	 *	Write SCSI command into the message - always 16 byte block 
-	 */
-	 
+	/* Write SCSI command into the message - always 16 byte block */
 	memcpy_toio(mptr, SCpnt->cmnd, 16);
-	mptr+=4;
-	lenptr=mptr++;		/* Remember me - fill in when we know */
-	
+	mptr += 4;
+	lenptr = mptr++;	/* Remember me - fill in when we know */
+
 	reqlen = 12;		// SINGLE SGE
-	
-	/*
-	 *	Now fill in the SGList and command 
-	 *
-	 *	FIXME: we need to set the sglist limits according to the 
-	 *	message size of the I2O controller. We might only have room
-	 *	for 6 or so worst case
-	 */
-	
-	if(SCpnt->use_sg)
-	{
-		struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer;
+
+	/* Now fill in the SGList and command */
+	if (SCpnt->use_sg) {
+		struct scatterlist *sg;
 		int sg_count;
-		int chain = 0;
-		
+
+		sg = SCpnt->request_buffer;
 		len = 0;
 
-		sg_count = pci_map_sg(c->pdev, sg, SCpnt->use_sg,
-				SCpnt->sc_data_direction);
+		sg_count = dma_map_sg(dev, sg, SCpnt->use_sg,
+				      SCpnt->sc_data_direction);
 
-		/* FIXME: handle fail */
-		if(!sg_count)
-			BUG();
-		
-		if((sg_max_frags > 11) && (SCpnt->use_sg > 11))
-		{
-			chain = 1;
-			/*
-			 *	Need to chain!
-			 */
-			i2o_raw_writel(direction|0xB0000000|(SCpnt->use_sg*2*4), mptr++);
-			i2o_raw_writel(virt_to_bus(sg_chain_pool + sg_chain_tag), mptr);
-			mptr = (u32*)(sg_chain_pool + sg_chain_tag);
-			if (SCpnt->use_sg > max_sg_len)
-			{
-				max_sg_len = SCpnt->use_sg;
-				printk("i2o_scsi: Chain SG! SCpnt=%p, SG_FragCnt=%d, SG_idx=%d\n",
-					SCpnt, SCpnt->use_sg, sg_chain_tag);
-			}
-			if ( ++sg_chain_tag == SG_MAX_BUFS )
-				sg_chain_tag = 0;
-			for(i = 0 ; i < SCpnt->use_sg; i++)
-			{
-				*mptr++=cpu_to_le32(direction|0x10000000|sg_dma_len(sg));
-				len+=sg_dma_len(sg);
-				*mptr++=cpu_to_le32(sg_dma_address(sg));
-				sg++;
-			}
-			mptr[-2]=cpu_to_le32(direction|0xD0000000|sg_dma_len(sg-1));
-		}
-		else
-		{		
-			for(i = 0 ; i < SCpnt->use_sg; i++)
-			{
-				i2o_raw_writel(direction|0x10000000|sg_dma_len(sg), mptr++);
-				len+=sg->length;
-				i2o_raw_writel(sg_dma_address(sg), mptr++);
-				sg++;
-			}
+		if (unlikely(sg_count <= 0))
+			return -ENOMEM;
 
-			/* Make this an end of list. Again evade the 920 bug and
-			   unwanted PCI read traffic */
-		
-			i2o_raw_writel(direction|0xD0000000|sg_dma_len(sg-1), &mptr[-2]);
-		}
-		
-		if(!chain)
-			reqlen = mptr - msg;
-		
-		i2o_raw_writel(len, lenptr);
-		
-		if(len != SCpnt->underflow)
-			printk("Cmd len %08X Cmd underflow %08X\n",
-				len, SCpnt->underflow);
-	}
-	else
-	{
-		dprintk(KERN_INFO "non sg for %p, %d\n", SCpnt->request_buffer,
-				SCpnt->request_bufflen);
-		i2o_raw_writel(len = SCpnt->request_bufflen, lenptr);
-		if(len == 0)
-		{
-			reqlen = 9;
+		for (i = SCpnt->use_sg; i > 0; i--) {
+			if (i == 1)
+				sg_flags |= 0xC0000000;
+			writel(sg_flags | sg_dma_len(sg), mptr++);
+			writel(sg_dma_address(sg), mptr++);
+			len += sg_dma_len(sg);
+			sg++;
 		}
-		else
-		{
+
+		reqlen = mptr - &msg->u.head[0];
+		writel(len, lenptr);
+	} else {
+		len = SCpnt->request_bufflen;
+
+		writel(len, lenptr);
+
+		if (len > 0) {
 			dma_addr_t dma_addr;
-			dma_addr = pci_map_single(c->pdev,
-					       SCpnt->request_buffer,
-					       SCpnt->request_bufflen,
-					       SCpnt->sc_data_direction);
-			if(dma_addr == 0)
-				BUG();	/* How to handle ?? */
-			SCpnt->SCp.ptr = (char *)(unsigned long) dma_addr;
-			i2o_raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++);
-			i2o_raw_writel(dma_addr, mptr++);
-		}
+
+			dma_addr = dma_map_single(dev, SCpnt->request_buffer,
+						  SCpnt->request_bufflen,
+						  SCpnt->sc_data_direction);
+			if (!dma_addr)
+				return -ENOMEM;
+
+			SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr;
+			sg_flags |= 0xC0000000;
+			writel(sg_flags | SCpnt->request_bufflen, mptr++);
+			writel(dma_addr, mptr++);
+		} else
+			reqlen = 9;
 	}
-	
-	/*
-	 *	Stick the headers on 
-	 */
 
-	i2o_raw_writel(reqlen<<16 | SGL_OFFSET_10, msg);
-	
+	/* Stick the headers on */
+	writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]);
+
 	/* Queue the message */
-	i2o_post_message(c,m);
-	
-	atomic_inc(&queue_depth);
-	
-	if(atomic_read(&queue_depth)> max_qd)
-	{
-		max_qd=atomic_read(&queue_depth);
-		printk("Queue depth now %d.\n", max_qd);
-	}
-	
-	mb();
-	dprintk(KERN_INFO "Issued %ld\n", current_command->serial_number);
-	
+	i2o_msg_post(c, m);
+
+	pr_debug("Issued %ld\n", SCpnt->serial_number);
+
 	return 0;
-}
+};
 
 /**
- *	i2o_scsi_abort	-	abort a running command
+ *	i2o_scsi_abort - abort a running command
  *	@SCpnt: command to abort
  *
  *	Ask the I2O controller to abort a command. This is an asynchrnous
- *	process and our callback handler will see the command complete
- *	with an aborted message if it succeeds. 
+ *	process and our callback handler will see the command complete with an
+ *	aborted message if it succeeds.
  *
- *	Locks: no locks are held or needed
+ *	Returns 0 if the command is successfully aborted or negative error code
+ *	on failure.
  */
- 
-static int i2o_scsi_abort(struct scsi_cmnd * SCpnt)
+int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
 {
+	struct i2o_device *i2o_dev;
 	struct i2o_controller *c;
-	struct Scsi_Host *host;
-	struct i2o_scsi_host *hostdata;
-	u32 msg[5];
+	struct i2o_message *msg;
+	u32 m;
 	int tid;
 	int status = FAILED;
-	
-	printk(KERN_WARNING "i2o_scsi: Aborting command block.\n");
-	
-	host = SCpnt->device->host;
-	hostdata = (struct i2o_scsi_host *)host->hostdata;
-	tid = hostdata->task[SCpnt->device->id][SCpnt->device->lun];
-	if(tid==-1)
-	{
-		printk(KERN_ERR "i2o_scsi: Impossible command to abort!\n");
-		return status;
-	}
-	c = hostdata->controller;
-
-	spin_unlock_irq(host->host_lock);
-		
-	msg[0] = FIVE_WORD_MSG_SIZE;
-	msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid;
-	msg[2] = scsi_context;
-	msg[3] = 0;
-	msg[4] = i2o_context_list_remove(SCpnt, c);
-	if(i2o_post_wait(c, msg, sizeof(msg), 240))
-		status = SUCCESS;
-
-	spin_lock_irq(host->host_lock);
-	return status;
-}
-
-/**
- *	i2o_scsi_bus_reset		-	Issue a SCSI reset
- *	@SCpnt: the command that caused the reset
- *
- *	Perform a SCSI bus reset operation. In I2O this is just a message
- *	we pass. I2O can do clever multi-initiator and shared reset stuff
- *	but we don't support this.
- *
- *	Locks: called with no lock held, requires no locks.
- */
- 
-static int i2o_scsi_bus_reset(struct scsi_cmnd * SCpnt)
-{
-	int tid;
-	struct i2o_controller *c;
-	struct Scsi_Host *host;
-	struct i2o_scsi_host *hostdata;
-	u32 m;
-	void *msg;
-	unsigned long timeout;
-
-	
-	/*
-	 *	Find the TID for the bus
-	 */
-
-	
-	host = SCpnt->device->host;
 
-	spin_unlock_irq(host->host_lock);
-
-	printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n");
-
-	hostdata = (struct i2o_scsi_host *)host->hostdata;
-	tid = hostdata->bus_task;
-	c = hostdata->controller;
+	printk(KERN_WARNING "i2o_scsi: Aborting command block.\n");
 
-	/*
-	 *	Now send a SCSI reset request. Any remaining commands
-	 *	will be aborted by the IOP. We need to catch the reply
-	 *	possibly ?
-	 */
+	i2o_dev = SCpnt->device->hostdata;
+	c = i2o_dev->iop;
+	tid = i2o_dev->lct_data.tid;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid,
+	       &msg->u.head[1]);
+	writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]);
 
-	timeout = jiffies+2*HZ;
-	do
-	{
-		m = le32_to_cpu(I2O_POST_READ32(c));
-		if(m != 0xFFFFFFFF)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-		mb();
-	}
-	while(time_before(jiffies, timeout));
-	
-	
-	msg = c->msg_virt + m;
-	i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg);
-	i2o_raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, msg+4);
-	i2o_raw_writel(scsi_context|0x80000000, msg+8);
-	/* We use the top bit to split controller and unit transactions */
-	/* Now store unit,tid so we can tie the completion back to a specific device */
-	__raw_writel(c->unit << 16 | tid, msg+12);
-	wmb();
-
-	/* We want the command to complete after we return */	
-	spin_lock_irq(host->host_lock);
-	i2o_post_message(c,m);
+	if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT))
+		status = SUCCESS;
 
-	/* Should we wait for the reset to complete ? */	
-	return SUCCESS;
+	return status;
 }
 
 /**
  *	i2o_scsi_bios_param	-	Invent disk geometry
- *	@sdev: scsi device 
+ *	@sdev: scsi device
  *	@dev: block layer device
  *	@capacity: size in sectors
  *	@ip: geometry array
  *
- *	This is anyones guess quite frankly. We use the same rules everyone 
+ *	This is anyones guess quite frankly. We use the same rules everyone
  *	else appears to and hope. It seems to work.
  */
- 
-static int i2o_scsi_bios_param(struct scsi_device * sdev,
-		struct block_device *dev, sector_t capacity, int *ip)
+
+static int i2o_scsi_bios_param(struct scsi_device *sdev,
+			       struct block_device *dev, sector_t capacity,
+			       int *ip)
 {
 	int size;
 
@@ -1023,25 +819,64 @@
 	return 0;
 }
 
-MODULE_AUTHOR("Red Hat Software");
-MODULE_LICENSE("GPL");
+static struct scsi_host_template i2o_scsi_host_template = {
+	.proc_name = "SCSI-OSM",
+	.name = "I2O SCSI Peripheral OSM",
+	.info = i2o_scsi_info,
+	.queuecommand = i2o_scsi_queuecommand,
+	.eh_abort_handler = i2o_scsi_abort,
+	.bios_param = i2o_scsi_bios_param,
+	.can_queue = I2O_SCSI_CAN_QUEUE,
+	.sg_tablesize = 8,
+	.cmd_per_lun = 6,
+	.use_clustering = ENABLE_CLUSTERING,
+};
+
+/*
+int
+i2o_scsi_queuecommand(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
+{
+	printk(KERN_INFO "queuecommand\n");
+	return SCSI_MLQUEUE_HOST_BUSY;
+};
+*/
+
+/**
+ *	i2o_scsi_init - SCSI OSM initialization function
+ *
+ *	Register SCSI OSM into I2O core.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_scsi_init(void)
+{
+	int rc;
 
+	printk(KERN_INFO "I2O SCSI Peripheral OSM\n");
 
-static struct scsi_host_template driver_template = {
-	.proc_name		= "i2o_scsi",
-	.name			= "I2O SCSI Layer",
-	.detect			= i2o_scsi_detect,
-	.release		= i2o_scsi_release,
-	.info			= i2o_scsi_info,
-	.queuecommand		= i2o_scsi_queuecommand,
-	.eh_abort_handler	= i2o_scsi_abort,
-	.eh_bus_reset_handler	= i2o_scsi_bus_reset,
-	.bios_param		= i2o_scsi_bios_param,
-	.can_queue		= I2O_SCSI_CAN_QUEUE,
-	.this_id		= 15,
-	.sg_tablesize		= 8,
-	.cmd_per_lun		= 6,
-	.use_clustering		= ENABLE_CLUSTERING,
+	/* Register SCSI OSM into I2O core */
+	rc = i2o_driver_register(&i2o_scsi_driver);
+	if (rc) {
+		printk(KERN_ERR "scsi-osm: Could not register SCSI driver\n");
+		return rc;
+	}
+
+	return 0;
 };
 
-#include "../../scsi/scsi_module.c"
+/**
+ *	i2o_scsi_exit - SCSI OSM exit function
+ *
+ *	Unregisters SCSI OSM from I2O core.
+ */
+static void __exit i2o_scsi_exit(void)
+{
+	/* Unregister I2O SCSI OSM from I2O core */
+	i2o_driver_unregister(&i2o_scsi_driver);
+};
+
+MODULE_AUTHOR("Red Hat Software");
+MODULE_LICENSE("GPL");
+
+module_init(i2o_scsi_init);
+module_exit(i2o_scsi_exit);
diff -Nru a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/message/i2o/iop.c	2004-08-19 09:24:16 -07:00
@@ -0,0 +1,1258 @@
+/*
+ *	Functions to handle I2O controllers and I2O message handling
+ *
+ *	Copyright (C) 1999-2002	Red Hat Software
+ *
+ *	Written by Alan Cox, Building Number Three Ltd
+ *
+ *	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 of the License, or (at your
+ *	option) any later version.
+ *
+ *	A lot of the I2O message side code from this is taken from the
+ *	Red Creek RCPCI45 adapter driver by Red Creek Communications
+ *
+ *	Fixes/additions:
+ *		Philipp Rumpf
+ *		Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ *		Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ *		Deepak Saxena <deepak@plexity.net>
+ *		Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
+ *		Alan Cox <alan@redhat.com>:
+ *			Ported to Linux 2.5.
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *			Minor fixes for 2.6.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+
+/* global I2O controller list */
+LIST_HEAD(i2o_controllers);
+
+/*
+ * global I2O System Table. Contains information about all the IOPs in the
+ * system. Used to inform IOPs about each others existence.
+ */
+static struct i2o_dma i2o_systab;
+
+/* Module internal functions from other sources */
+extern struct i2o_driver i2o_exec_driver;
+extern int i2o_exec_lct_get(struct i2o_controller *);
+extern void i2o_device_remove(struct i2o_device *);
+
+extern int __init i2o_driver_init(void);
+extern void __exit i2o_driver_exit(void);
+extern int __init i2o_exec_init(void);
+extern void __exit i2o_exec_exit(void);
+extern int __init i2o_pci_init(void);
+extern void __exit i2o_pci_exit(void);
+extern int i2o_device_init(void);
+extern void i2o_device_exit(void);
+
+/**
+ *	i2o_msg_nop - Returns a message which is not used
+ *	@c: I2O controller from which the message was created
+ *	@m: message which should be returned
+ *
+ *	If you fetch a message via i2o_msg_get, and can't use it, you must
+ *	return the message with this function. Otherwise the message frame
+ *	is lost.
+ */
+void i2o_msg_nop(struct i2o_controller *c, u32 m)
+{
+	struct i2o_message *msg = c->in_queue.virt + m;
+
+	writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(0, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+	i2o_msg_post(c, m);
+};
+
+/**
+ *	i2o_msg_get_wait - obtain an I2O message from the IOP
+ *	@c: I2O controller
+ *	@msg: pointer to a I2O message pointer
+ *	@wait: how long to wait until timeout
+ *
+ *	This function waits up to wait seconds for a message slot to be
+ *	available.
+ *
+ *	On a success the message is returned and the pointer to the message is
+ *	set in msg. The returned message is the physical page frame offset
+ *	address from the read port (see the i2o spec). If no message is
+ *	available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
+ */
+u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message **msg,
+		     int wait)
+{
+	unsigned long timeout = jiffies + wait * HZ;
+	u32 m;
+
+	while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
+		if (time_after(jiffies, timeout)) {
+			pr_debug("%s: Timeout waiting for message frame.\n",
+				 c->name);
+			return I2O_QUEUE_EMPTY;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+
+	return m;
+};
+
+#if BITS_PER_LONG == 64
+/**
+ *      i2o_cntxt_list_add - Append a pointer to context list and return a id
+ *	@c: controller to which the context list belong
+ *	@ptr: pointer to add to the context list
+ *
+ *	Because the context field in I2O is only 32-bit large, on 64-bit the
+ *	pointer is to large to fit in the context field. The i2o_cntxt_list
+ *	functions therefore map pointers to context fields.
+ *
+ *	Returns context id > 0 on success or 0 on failure.
+ */
+u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
+{
+	struct i2o_context_list_element *entry;
+	unsigned long flags;
+
+	if (!ptr)
+		printk(KERN_ERR "NULL pointer found!\n");
+
+	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+	if (!entry) {
+		printk(KERN_ERR "i2o: Could not allocate memory for context "
+		       "list element\n");
+		return 0;
+	}
+
+	entry->ptr = ptr;
+	entry->timestamp = jiffies;
+	INIT_LIST_HEAD(&entry->list);
+
+	spin_lock_irqsave(&c->context_list_lock, flags);
+
+	if (unlikely(atomic_inc_and_test(&c->context_list_counter)))
+		atomic_inc(&c->context_list_counter);
+
+	entry->context = atomic_read(&c->context_list_counter);
+
+	list_add(&entry->list, &c->context_list);
+
+	spin_unlock_irqrestore(&c->context_list_lock, flags);
+
+	pr_debug("Add context to list %p -> %d\n", ptr, context);
+
+	return entry->context;
+};
+
+/**
+ *      i2o_cntxt_list_remove - Remove a pointer from the context list
+ *	@c: controller to which the context list belong
+ *	@ptr: pointer which should be removed from the context list
+ *
+ *	Removes a previously added pointer from the context list and returns
+ *	the matching context id.
+ *
+ *	Returns context id on succes or 0 on failure.
+ */
+u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr)
+{
+	struct i2o_context_list_element *entry;
+	u32 context = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->context_list_lock, flags);
+	list_for_each_entry(entry, &c->context_list, list)
+	    if (entry->ptr == ptr) {
+		list_del(&entry->list);
+		context = entry->context;
+		kfree(entry);
+		break;
+	}
+	spin_unlock_irqrestore(&c->context_list_lock, flags);
+
+	if (!context)
+		printk(KERN_WARNING "i2o: Could not remove nonexistent ptr "
+		       "%p\n", ptr);
+
+	pr_debug("remove ptr from context list %d -> %p\n", context, ptr);
+
+	return context;
+};
+
+/**
+ *      i2o_cntxt_list_get - Get a pointer from the context list and remove it
+ *	@c: controller to which the context list belong
+ *	@context: context id to which the pointer belong
+ *
+ *	Returns pointer to the matching context id on success or NULL on
+ *	failure.
+ */
+void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context)
+{
+	struct i2o_context_list_element *entry;
+	unsigned long flags;
+	void *ptr = NULL;
+
+	spin_lock_irqsave(&c->context_list_lock, flags);
+	list_for_each_entry(entry, &c->context_list, list)
+	    if (entry->context == context) {
+		list_del(&entry->list);
+		ptr = entry->ptr;
+		kfree(entry);
+		break;
+	}
+	spin_unlock_irqrestore(&c->context_list_lock, flags);
+
+	if (!ptr)
+		printk(KERN_WARNING "i2o: context id %d not found\n", context);
+
+	pr_debug("get ptr from context list %d -> %p\n", context, ptr);
+
+	return ptr;
+};
+
+/**
+ *      i2o_cntxt_list_get_ptr - Get a context id from the context list
+ *	@c: controller to which the context list belong
+ *	@ptr: pointer to which the context id should be fetched
+ *
+ *	Returns context id which matches to the pointer on succes or 0 on
+ *	failure.
+ */
+u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr)
+{
+	struct i2o_context_list_element *entry;
+	u32 context = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->context_list_lock, flags);
+	list_for_each_entry(entry, &c->context_list, list)
+	    if (entry->ptr == ptr) {
+		context = entry->context;
+		break;
+	}
+	spin_unlock_irqrestore(&c->context_list_lock, flags);
+
+	if (!context)
+		printk(KERN_WARNING "i2o: Could not find nonexistent ptr "
+		       "%p\n", ptr);
+
+	pr_debug("get context id from context list %p -> %d\n", ptr, context);
+
+	return context;
+};
+#endif
+
+/**
+ *	i2o_iop_find - Find an I2O controller by id
+ *	@unit: unit number of the I2O controller to search for
+ *
+ *	Lookup the I2O controller on the controller list.
+ *
+ *	Returns pointer to the I2O controller on success or NULL if not found.
+ */
+struct i2o_controller *i2o_find_iop(int unit)
+{
+	struct i2o_controller *c;
+
+	list_for_each_entry(c, &i2o_controllers, list) {
+		if (c->unit == unit)
+			return c;
+	}
+
+	return NULL;
+};
+
+/**
+ *	i2o_iop_find_device - Find a I2O device on an I2O controller
+ *	@c: I2O controller where the I2O device hangs on
+ *	@tid: TID of the I2O device to search for
+ *
+ *	Searches the devices of the I2O controller for a device with TID tid and
+ *	returns it.
+ *
+ *	Returns a pointer to the I2O device if found, otherwise NULL.
+ */
+struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid)
+{
+	struct i2o_device *dev;
+
+	list_for_each_entry(dev, &c->devices, list)
+	    if (dev->lct_data.tid == tid)
+		return dev;
+
+	return 0;
+};
+
+/**
+ *	i2o_quiesce_controller - quiesce controller
+ *	@c: controller
+ *
+ *	Quiesce an IOP. Causes IOP to make external operation quiescent
+ *	(i2o 'READY' state). Internal operation of the IOP continues normally.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_iop_quiesce(struct i2o_controller *c)
+{
+	struct i2o_message *msg;
+	u32 m;
+	i2o_status_block *sb = c->status_block.virt;
+	int rc;
+
+	i2o_status_get(c);
+
+	/* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
+	if ((sb->iop_state != ADAPTER_STATE_READY) &&
+	    (sb->iop_state != ADAPTER_STATE_OPERATIONAL))
+		return 0;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+
+	/* Long timeout needed for quiesce if lots of devices */
+	if ((rc = i2o_msg_post_wait(c, m, 240)))
+		printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n",
+		       c->name, -rc);
+	else
+		pr_debug("%s: Quiesced.\n", c->name);
+
+	i2o_status_get(c);	// Entered READY state
+
+	return rc;
+};
+
+/**
+ *	i2o_iop_enable - move controller from ready to OPERATIONAL
+ *	@c: I2O controller
+ *
+ *	Enable IOP. This allows the IOP to resume external operations and
+ *	reverses the effect of a quiesce. Returns zero or an error code if
+ *	an error occurs.
+ */
+static int i2o_iop_enable(struct i2o_controller *c)
+{
+	struct i2o_message *msg;
+	u32 m;
+	i2o_status_block *sb = c->status_block.virt;
+	int rc;
+
+	i2o_status_get(c);
+
+	/* Enable only allowed on READY state */
+	if (sb->iop_state != ADAPTER_STATE_READY)
+		return -EINVAL;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+
+	/* How long of a timeout do we need? */
+	if ((rc = i2o_msg_post_wait(c, m, 240)))
+		printk(KERN_ERR "%s: Could not enable (status=%#x).\n",
+		       c->name, -rc);
+	else
+		pr_debug("%s: Enabled.\n", c->name);
+
+	i2o_status_get(c);	// entered OPERATIONAL state
+
+	return rc;
+};
+
+/**
+ *	i2o_iop_quiesce_all - Quiesce all I2O controllers on the system
+ *
+ *	Quiesce all I2O controllers which are connected to the system.
+ */
+static inline void i2o_iop_quiesce_all(void)
+{
+	struct i2o_controller *c, *tmp;
+
+	list_for_each_entry_safe(c, tmp, &i2o_controllers, list) {
+		if (!c->no_quiesce)
+			i2o_iop_quiesce(c);
+	}
+};
+
+/**
+ *	i2o_iop_enable_all - Enables all controllers on the system
+ *
+ *	Enables all I2O controllers which are connected to the system.
+ */
+static inline void i2o_iop_enable_all(void)
+{
+	struct i2o_controller *c, *tmp;
+
+	list_for_each_entry_safe(c, tmp, &i2o_controllers, list)
+	    i2o_iop_enable(c);
+};
+
+/**
+ *	i2o_clear_controller - Bring I2O controller into HOLD state
+ *	@c: controller
+ *
+ *	Clear an IOP to HOLD state, ie. terminate external operations, clear all
+ *	input queues and prepare for a system restart. IOP's internal operation
+ *	continues normally and the outbound queue is alive. The IOP is not
+ *	expected to rebuild its LCT.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_iop_clear(struct i2o_controller *c)
+{
+	struct i2o_message *msg;
+	u32 m;
+	int rc;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	/* Quiesce all IOPs first */
+	i2o_iop_quiesce_all();
+
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+
+	if ((rc = i2o_msg_post_wait(c, m, 30)))
+		printk(KERN_INFO "%s: Unable to clear (status=%#x).\n",
+		       c->name, -rc);
+	else
+		pr_debug("%s: Cleared.\n", c->name);
+
+	/* Enable all IOPs */
+	i2o_iop_enable_all();
+
+	i2o_status_get(c);
+
+	return rc;
+}
+
+/**
+ *	i2o_iop_reset - reset an I2O controller
+ *	@c: controller to reset
+ *
+ *	Reset the IOP into INIT state and wait until IOP gets into RESET state.
+ *	Terminate all external operations, clear IOP's inbound and outbound
+ *	queues, terminate all DDMs, and reload the IOP's operating environment
+ *	and all local DDMs. The IOP rebuilds its LCT.
+ */
+static int i2o_iop_reset(struct i2o_controller *c)
+{
+	u8 *status = c->status.virt;
+	struct i2o_message *msg;
+	u32 m;
+	unsigned long timeout;
+	i2o_status_block *sb = c->status_block.virt;
+	int rc = 0;
+
+	pr_debug("Resetting controller\n");
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	memset(status, 0, 4);
+
+	/* Quiesce all IOPs first */
+	i2o_iop_quiesce_all();
+
+	writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+	writel(0, &msg->u.s.tcntxt);	//FIXME: use reasonable transaction context
+	writel(0, &msg->body[0]);
+	writel(0, &msg->body[1]);
+	writel(i2o_ptr_low((void *)c->status.phys), &msg->body[2]);
+	writel(i2o_ptr_high((void *)c->status.phys), &msg->body[3]);
+
+	i2o_msg_post(c, m);
+
+	/* Wait for a reply */
+	timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
+	while (!*status) {
+		if (time_after(jiffies, timeout)) {
+			printk(KERN_ERR "IOP reset timeout.\n");
+			rc = -ETIMEDOUT;
+			goto exit;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+
+		rmb();
+	}
+
+	if (*status == I2O_CMD_IN_PROGRESS) {
+		/*
+		 * Once the reset is sent, the IOP goes into the INIT state
+		 * which is indeterminate.  We need to wait until the IOP
+		 * has rebooted before we can let the system talk to
+		 * it. We read the inbound Free_List until a message is
+		 * available. If we can't read one in the given ammount of
+		 * time, we assume the IOP could not reboot properly.
+		 */
+		pr_debug("%s: Reset in progress, waiting for reboot...\n",
+			 c->name);
+
+		m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
+		while (m == I2O_QUEUE_EMPTY) {
+			if (time_after(jiffies, timeout)) {
+				printk(KERN_ERR "IOP reset timeout.\n");
+				rc = -ETIMEDOUT;
+				goto exit;
+			}
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+
+			m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
+		}
+		i2o_msg_nop(c, m);
+	}
+
+	/* from here all quiesce commands are safe */
+	c->no_quiesce = 0;
+
+	/* If IopReset was rejected or didn't perform reset, try IopClear */
+	i2o_status_get(c);
+	if (*status == I2O_CMD_REJECTED || sb->iop_state != ADAPTER_STATE_RESET) {
+		printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",
+		       c->name);
+		i2o_iop_clear(c);
+	} else
+		pr_debug("%s: Reset completed.\n", c->name);
+
+      exit:
+	/* Enable all IOPs */
+	i2o_iop_enable_all();
+
+	return rc;
+};
+
+/**
+ *	i2o_iop_init_outbound_queue - setup the outbound message queue
+ *	@c: I2O controller
+ *
+ *	Clear and (re)initialize IOP's outbound queue and post the message
+ *	frames to the IOP.
+ *
+ *	Returns 0 on success or a negative errno code on failure.
+ */
+int i2o_iop_init_outbound_queue(struct i2o_controller *c)
+{
+	u8 *status = c->status.virt;
+	u32 m;
+	struct i2o_message *msg;
+	ulong timeout;
+	int i;
+
+	pr_debug("%s: Initializing Outbound Queue...\n", c->name);
+
+	memset(status, 0, 4);
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]);
+	writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+	writel(0x0106, &msg->u.s.tcntxt);	/* FIXME: why 0x0106, maybe in
+						   Spec? */
+	writel(PAGE_SIZE, &msg->body[0]);
+	writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);	/* Outbound msg frame
+								   size in words and Initcode */
+	writel(0xd0000004, &msg->body[2]);
+	writel(i2o_ptr_low((void *)c->status.phys), &msg->body[3]);
+	writel(i2o_ptr_high((void *)c->status.phys), &msg->body[4]);
+
+	i2o_msg_post(c, m);
+
+	timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
+	while (*status <= I2O_CMD_IN_PROGRESS) {
+		if (time_after(jiffies, timeout)) {
+			printk(KERN_WARNING "%s: Timeout Initializing\n",
+			       c->name);
+			return -ETIMEDOUT;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+
+		rmb();
+	}
+
+	m = c->out_queue.phys;
+
+	/* Post frames */
+	for (i = 0; i < NMBR_MSG_FRAMES; i++) {
+		i2o_flush_reply(c, m);
+		m += MSG_FRAME_SIZE * 4;
+	}
+
+	return 0;
+}
+
+/**
+ *	i2o_iop_activate - Bring controller up to HOLD
+ *	@c: controller
+ *
+ *	This function brings an I2O controller into HOLD state. The adapter
+ *	is reset if necessary and then the queues and resource table are read.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_iop_activate(struct i2o_controller *c)
+{
+	i2o_status_block *sb = c->status_block.virt;
+	int rc;
+	/* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
+	/* In READY state, Get status */
+
+	rc = i2o_status_get(c);
+	if (rc) {
+		printk(KERN_INFO "Unable to obtain status of %s, "
+		       "attempting a reset.\n", c->name);
+		if (i2o_iop_reset(c))
+			return rc;
+	}
+
+	if (sb->i2o_version > I2OVER15) {
+		printk(KERN_ERR "%s: Not running vrs. 1.5. of the I2O "
+		       "Specification.\n", c->name);
+		return -ENODEV;
+	}
+
+	switch (sb->iop_state) {
+	case ADAPTER_STATE_FAULTED:
+		printk(KERN_CRIT "%s: hardware fault\n", c->name);
+		return -ENODEV;
+
+	case ADAPTER_STATE_READY:
+	case ADAPTER_STATE_OPERATIONAL:
+	case ADAPTER_STATE_HOLD:
+	case ADAPTER_STATE_FAILED:
+		pr_debug("already running, trying to reset...\n");
+		if (i2o_iop_reset(c))
+			return -ENODEV;
+	}
+
+	rc = i2o_iop_init_outbound_queue(c);
+	if (rc)
+		return rc;
+
+	/* In HOLD state */
+
+	rc = i2o_hrt_get(c);
+	if (rc)
+		return rc;
+
+	return 0;
+};
+
+/**
+ *	i2o_iop_systab_set - Set the I2O System Table of the specified IOP
+ *	@c: I2O controller to which the system table should be send
+ *
+ *	Before the systab could be set i2o_systab_build() must be called.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_iop_systab_set(struct i2o_controller *c)
+{
+	struct i2o_message *msg;
+	u32 m;
+	i2o_status_block *sb = c->status_block.virt;
+	struct device *dev = &c->pdev->dev;
+	struct resource *root;
+	int rc;
+
+	if (sb->current_mem_size < sb->desired_mem_size) {
+		struct resource *res = &c->mem_resource;
+		res->name = c->pdev->bus->name;
+		res->flags = IORESOURCE_MEM;
+		res->start = 0;
+		res->end = 0;
+		printk("%s: requires private memory resources.\n", c->name);
+		root = pci_find_parent_resource(c->pdev, res);
+		if (root == NULL)
+			printk("Can't find parent resource!\n");
+		if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20,	/* Unspecified, so use 1Mb and play safe */
+					      NULL, NULL) >= 0) {
+			c->mem_alloc = 1;
+			sb->current_mem_size = 1 + res->end - res->start;
+			sb->current_mem_base = res->start;
+			printk(KERN_INFO
+			       "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n",
+			       c->name, 1 + res->end - res->start, res->start);
+		}
+	}
+
+	if (sb->current_io_size < sb->desired_io_size) {
+		struct resource *res = &c->io_resource;
+		res->name = c->pdev->bus->name;
+		res->flags = IORESOURCE_IO;
+		res->start = 0;
+		res->end = 0;
+		printk("%s: requires private memory resources.\n", c->name);
+		root = pci_find_parent_resource(c->pdev, res);
+		if (root == NULL)
+			printk("Can't find parent resource!\n");
+		if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20,	/* Unspecified, so use 1Mb and play safe */
+					      NULL, NULL) >= 0) {
+			c->io_alloc = 1;
+			sb->current_io_size = 1 + res->end - res->start;
+			sb->current_mem_base = res->start;
+			printk(KERN_INFO
+			       "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n",
+			       c->name, 1 + res->end - res->start, res->start);
+		}
+	}
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len,
+					 PCI_DMA_TODEVICE);
+	if (!i2o_systab.phys) {
+		i2o_msg_nop(c, m);
+		return -ENOMEM;
+	}
+
+	writel(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6, &msg->u.head[0]);
+	writel(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+
+	/*
+	 * Provide three SGL-elements:
+	 * System table (SysTab), Private memory space declaration and
+	 * Private i/o space declaration
+	 *
+	 * FIXME: is this still true?
+	 * Nasty one here. We can't use dma_alloc_coherent to send the
+	 * same table to everyone. We have to go remap it for them all
+	 */
+
+	writel(c->unit + 2, &msg->body[0]);
+	writel(0, &msg->body[1]);
+	writel(0x54000000 | i2o_systab.phys, &msg->body[2]);
+	writel(i2o_systab.phys, &msg->body[3]);
+	writel(0x54000000 | sb->current_mem_size, &msg->body[4]);
+	writel(sb->current_mem_base, &msg->body[5]);
+	writel(0xd4000000 | sb->current_io_size, &msg->body[6]);
+	writel(sb->current_io_base, &msg->body[6]);
+
+	rc = i2o_msg_post_wait(c, m, 120);
+
+	dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len,
+			 PCI_DMA_TODEVICE);
+
+	if (rc < 0)
+		printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n",
+		       c->name, -rc);
+	else
+		pr_debug("%s: SysTab set.\n", c->name);
+
+	i2o_status_get(c);	// Entered READY state
+
+	return rc;
+}
+
+/**
+ *	i2o_iop_online - Bring a controller online into OPERATIONAL state.
+ *	@c: I2O controller
+ *
+ *	Send the system table and enable the I2O controller.
+ *
+ *	Returns 0 on success or negativer error code on failure.
+ */
+static int i2o_iop_online(struct i2o_controller *c)
+{
+	int rc;
+
+	rc = i2o_iop_systab_set(c);
+	if (rc)
+		return rc;
+
+	/* In READY state */
+	pr_debug("%s: Attempting to enable...\n", c->name);
+	rc = i2o_iop_enable(c);
+	if (rc)
+		return rc;
+
+	return 0;
+};
+
+/**
+ *	i2o_iop_remove - Remove the I2O controller from the I2O core
+ *	@c: I2O controller
+ *
+ *	Remove the I2O controller from the I2O core. If devices are attached to
+ *	the controller remove these also and finally reset the controller.
+ */
+void i2o_iop_remove(struct i2o_controller *c)
+{
+	struct i2o_device *dev, *tmp;
+
+	pr_debug("Deleting controller %s\n", c->name);
+
+	i2o_driver_notify_controller_remove_all(c);
+
+	list_del(&c->list);
+
+	list_for_each_entry_safe(dev, tmp, &c->devices, list)
+	    i2o_device_remove(dev);
+
+	/* Ask the IOP to switch to RESET state */
+	i2o_iop_reset(c);
+}
+
+/**
+ *	i2o_systab_build - Build system table
+ *
+ *	The system table contains information about all the IOPs in the system
+ *	(duh) and is used by the Executives on the IOPs to establish peer2peer
+ *	connections. We're not supporting peer2peer at the moment, but this
+ *	will be needed down the road for things like lan2lan forwarding.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_systab_build(void)
+{
+	struct i2o_controller *c, *tmp;
+	int num_controllers = 0;
+	u32 change_ind = 0;
+	int count = 0;
+	struct i2o_sys_tbl *systab = i2o_systab.virt;
+
+	list_for_each_entry_safe(c, tmp, &i2o_controllers, list)
+	    num_controllers++;
+
+	if (systab) {
+		change_ind = systab->change_ind;
+		kfree(i2o_systab.virt);
+	}
+
+	/* Header + IOPs */
+	i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers *
+	    sizeof(struct i2o_sys_tbl_entry);
+
+	systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);
+	if (!systab) {
+		printk(KERN_ERR "i2o: unable to allocate memory for System "
+		       "Table\n");
+		return -ENOMEM;
+	}
+	memset(systab, 0, i2o_systab.len);
+
+	systab->version = I2OVERSION;
+	systab->change_ind = change_ind + 1;
+
+	list_for_each_entry_safe(c, tmp, &i2o_controllers, list) {
+		i2o_status_block *sb;
+
+		if (count >= num_controllers) {
+			printk(KERN_ERR "i2o: controller added while building "
+			       "system table\n");
+			break;
+		}
+
+		sb = c->status_block.virt;
+
+		/*
+		 * Get updated IOP state so we have the latest information
+		 *
+		 * We should delete the controller at this point if it
+		 * doesn't respond since if it's not on the system table
+		 * it is techninically not part of the I2O subsystem...
+		 */
+		if (unlikely(i2o_status_get(c))) {
+			printk(KERN_ERR "%s: Deleting b/c could not get status"
+			       " while attempting to build system table\n",
+			       c->name);
+			i2o_iop_remove(c);
+			continue;	// try the next one
+		}
+
+		systab->iops[count].org_id = sb->org_id;
+		systab->iops[count].iop_id = c->unit + 2;
+		systab->iops[count].seg_num = 0;
+		systab->iops[count].i2o_version = sb->i2o_version;
+		systab->iops[count].iop_state = sb->iop_state;
+		systab->iops[count].msg_type = sb->msg_type;
+		systab->iops[count].frame_size = sb->inbound_frame_size;
+		systab->iops[count].last_changed = change_ind;
+		systab->iops[count].iop_capabilities = sb->iop_capabilities;
+		systab->iops[count].inbound_low = i2o_ptr_low(c->post_port);
+		systab->iops[count].inbound_high = i2o_ptr_high(c->post_port);
+
+		count++;
+	}
+
+	systab->num_entries = count;
+
+	return 0;
+};
+
+/**
+ *	i2o_parse_hrt - Parse the hardware resource table.
+ *	@c: I2O controller
+ *
+ *	We don't do anything with it except dumping it (in debug mode).
+ *
+ *	Returns 0.
+ */
+static int i2o_parse_hrt(struct i2o_controller *c)
+{
+	i2o_dump_hrt(c);
+	return 0;
+};
+
+/**
+ *	i2o_status_get - Get the status block from the I2O controller
+ *	@c: I2O controller
+ *
+ *	Issue a status query on the controller. This updates the attached
+ *	status block. The status block could then be accessed through
+ *	c->status_block.
+ *
+ *	Returns 0 on sucess or negative error code on failure.
+ */
+int i2o_status_get(struct i2o_controller *c)
+{
+	struct i2o_message *msg;
+	u32 m;
+	u8 *status_block;
+	unsigned long timeout;
+
+	status_block = (u8 *) c->status_block.virt;
+	memset(status_block, 0, sizeof(i2o_status_block));
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+	writel(0, &msg->u.s.tcntxt);	// FIXME: use resonable transaction context
+	writel(0, &msg->body[0]);
+	writel(0, &msg->body[1]);
+	writel(i2o_ptr_low((void *)c->status_block.phys), &msg->body[2]);
+	writel(i2o_ptr_high((void *)c->status_block.phys), &msg->body[3]);
+	writel(sizeof(i2o_status_block), &msg->body[4]);	/* always 88 bytes */
+
+	i2o_msg_post(c, m);
+
+	/* Wait for a reply */
+	timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
+	while (status_block[87] != 0xFF) {
+		if (time_after(jiffies, timeout)) {
+			printk(KERN_ERR "%s: Get status timeout.\n", c->name);
+			return -ETIMEDOUT;
+		}
+
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+
+		rmb();
+	}
+
+#if DEBUG
+	i2o_debug_state(c);
+#endif
+
+	return 0;
+}
+
+/*
+ *	i2o_hrt_get - Get the Hardware Resource Table from the I2O controller
+ *	@c: I2O controller from which the HRT should be fetched
+ *
+ *	The HRT contains information about possible hidden devices but is
+ *	mostly useless to us.
+ *
+ *	Returns 0 on success or negativer error code on failure.
+ */
+int i2o_hrt_get(struct i2o_controller *c)
+{
+	int rc;
+	int i;
+	i2o_hrt *hrt = c->hrt.virt;
+	u32 size = sizeof(i2o_hrt);
+	struct device *dev = &c->pdev->dev;
+
+	for (i = 0; i < I2O_HRT_GET_TRIES; i++) {
+		struct i2o_message *msg;
+		u32 m;
+
+		m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+		if (m == I2O_QUEUE_EMPTY)
+			return -ETIMEDOUT;
+
+		writel(SIX_WORD_MSG_SIZE | SGL_OFFSET_4, &msg->u.head[0]);
+		writel(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
+		       &msg->u.head[1]);
+		writel(0xd0000000 | c->hrt.len, &msg->body[0]);
+		writel(c->hrt.phys, &msg->body[1]);
+
+		rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt);
+
+		if (rc < 0) {
+			printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",
+			       c->name, -rc);
+			return rc;
+		}
+
+		size = hrt->num_entries * hrt->entry_len << 2;
+		if (size > c->hrt.len) {
+			if (i2o_dma_realloc(dev, &c->hrt, size, GFP_KERNEL))
+				return -ENOMEM;
+			else
+				hrt = c->hrt.virt;
+		} else
+			return i2o_parse_hrt(c);
+	}
+
+	printk(KERN_ERR "%s: Unable to get HRT after %d tries, giving up\n",
+	       c->name, I2O_HRT_GET_TRIES);
+
+	return -EBUSY;
+}
+
+/**
+ *	i2o_iop_alloc - Allocate and initialize a i2o_controller struct
+ *
+ *	Allocate the necessary memory for a i2o_controller struct and
+ *	initialize the lists.
+ *
+ *	Returns a pointer to the I2O controller or a negative error code on
+ *	failure.
+ */
+struct i2o_controller *i2o_iop_alloc(void)
+{
+	static int unit = 0;	/* 0 and 1 are NULL IOP and Local Host */
+	struct i2o_controller *c;
+
+	c = kmalloc(sizeof(*c), GFP_KERNEL);
+	if (!c) {
+		printk(KERN_ERR "i2o: Insufficient memory to allocate the "
+		       "controller.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	memset(c, 0, sizeof(*c));
+
+	INIT_LIST_HEAD(&c->devices);
+	c->lock = SPIN_LOCK_UNLOCKED;
+	init_MUTEX(&c->lct_lock);
+	c->unit = unit++;
+	sprintf(c->name, "iop%d", c->unit);
+
+#if BITS_PER_LONG == 64
+	c->context_list_lock = SPIN_LOCK_UNLOCKED;
+	atomic_set(&c->context_list_counter, 0);
+	INIT_LIST_HEAD(&c->context_list);
+#endif
+
+	return c;
+};
+
+/**
+ *	i2o_iop_free - Free the i2o_controller struct
+ *	@c: I2O controller to free
+ */
+void i2o_iop_free(struct i2o_controller *c)
+{
+	kfree(c);
+};
+
+/**
+ *	i2o_iop_add - Initialize the I2O controller and add him to the I2O core
+ *	@c: controller
+ *
+ *	Initialize the I2O controller and if no error occurs add him to the I2O
+ *	core.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+int i2o_iop_add(struct i2o_controller *c)
+{
+	int rc;
+
+	printk(KERN_INFO "%s: Activating I2O controller...\n", c->name);
+	printk(KERN_INFO "%s: This may take a few minutes if there are many "
+	       "devices\n", c->name);
+
+	if ((rc = i2o_iop_activate(c))) {
+		printk(KERN_ERR "%s: controller could not activated\n",
+		       c->name);
+		i2o_iop_reset(c);
+		return rc;
+	}
+
+	pr_debug("building sys table %s...\n", c->name);
+
+	if ((rc = i2o_systab_build())) {
+		i2o_iop_reset(c);
+		return rc;
+	}
+
+	pr_debug("online controller %s...\n", c->name);
+
+	if ((rc = i2o_iop_online(c))) {
+		i2o_iop_reset(c);
+		return rc;
+	}
+
+	pr_debug("getting LCT %s...\n", c->name);
+
+	if ((rc = i2o_exec_lct_get(c))) {
+		i2o_iop_reset(c);
+		return rc;
+	}
+
+	list_add(&c->list, &i2o_controllers);
+
+	i2o_driver_notify_controller_add_all(c);
+
+	printk(KERN_INFO "%s: Controller added\n", c->name);
+
+	return 0;
+};
+
+/**
+ *	i2o_event_register - Turn on/off event notification for a I2O device
+ *	@dev: I2O device which should receive the event registration request
+ *	@drv: driver which want to get notified
+ *	@tcntxt: transaction context to use with this notifier
+ *	@evt_mask: mask of events
+ *
+ *	Create and posts an event registration message to the task. No reply
+ *	is waited for, or expected. If you do not want further notifications,
+ *	call the i2o_event_register again with a evt_mask of 0.
+ *
+ *	Returns 0 on success or -ETIMEDOUT if no message could be fetched for
+ *	sending the request.
+ */
+int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv,
+		       int tcntxt, u32 evt_mask)
+{
+	struct i2o_controller *c = dev->iop;
+	struct i2o_message *msg;
+	u32 m;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->lct_data.
+	       tid, &msg->u.head[1]);
+	writel(drv->context, &msg->u.s.icntxt);
+	writel(tcntxt, &msg->u.s.tcntxt);
+	writel(evt_mask, &msg->body[0]);
+
+	i2o_msg_post(c, m);
+
+	return 0;
+};
+
+/**
+ *	i2o_iop_init - I2O main initialization function
+ *
+ *	Initialize the I2O drivers (OSM) functions, register the Executive OSM,
+ *	initialize the I2O PCI part and finally initialize I2O device stuff.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_iop_init(void)
+{
+	int rc = 0;
+
+	printk(KERN_INFO "I2O Core - (C) Copyright 1999 Red Hat Software\n");
+
+	rc = i2o_device_init();
+	if (rc)
+		goto exit;
+
+	rc = i2o_driver_init();
+	if (rc)
+		goto device_exit;
+
+	rc = i2o_exec_init();
+	if (rc)
+		goto driver_exit;
+
+	rc = i2o_pci_init();
+	if (rc < 0)
+		goto exec_exit;
+
+	return 0;
+
+      exec_exit:
+	i2o_exec_exit();
+
+      driver_exit:
+	i2o_driver_exit();
+
+      device_exit:
+	i2o_device_exit();
+
+      exit:
+	return rc;
+}
+
+/**
+ *	i2o_iop_exit - I2O main exit function
+ *
+ *	Removes I2O controllers from PCI subsystem and shut down OSMs.
+ */
+static void __exit i2o_iop_exit(void)
+{
+	i2o_pci_exit();
+	i2o_exec_exit();
+	i2o_driver_exit();
+	i2o_device_exit();
+};
+
+module_init(i2o_iop_init);
+module_exit(i2o_iop_exit);
+
+MODULE_AUTHOR("Red Hat Software");
+MODULE_DESCRIPTION("I2O Core");
+MODULE_LICENSE("GPL");
+
+#if BITS_PER_LONG == 64
+EXPORT_SYMBOL(i2o_cntxt_list_add);
+EXPORT_SYMBOL(i2o_cntxt_list_get);
+EXPORT_SYMBOL(i2o_cntxt_list_remove);
+EXPORT_SYMBOL(i2o_cntxt_list_get_ptr);
+#endif
+EXPORT_SYMBOL(i2o_msg_get_wait);
+EXPORT_SYMBOL(i2o_msg_nop);
+EXPORT_SYMBOL(i2o_find_iop);
+EXPORT_SYMBOL(i2o_iop_find_device);
+EXPORT_SYMBOL(i2o_event_register);
+EXPORT_SYMBOL(i2o_status_get);
+EXPORT_SYMBOL(i2o_hrt_get);
+EXPORT_SYMBOL(i2o_controllers);
diff -Nru a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/message/i2o/pci.c	2004-08-24 11:29:33 -07:00
@@ -0,0 +1,513 @@
+/*
+ *	PCI handling of I2O controller
+ *
+ * 	Copyright (C) 1999-2002	Red Hat Software
+ *
+ *	Written by Alan Cox, Building Number Three Ltd
+ *
+ *	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 of the License, or (at your
+ *	option) any later version.
+ *
+ *	A lot of the I2O message side code from this is taken from the Red
+ *	Creek RCPCI45 adapter driver by Red Creek Communications
+ *
+ *	Fixes/additions:
+ *		Philipp Rumpf
+ *		Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ *		Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ *		Deepak Saxena <deepak@plexity.net>
+ *		Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
+ *		Alan Cox <alan@redhat.com>:
+ *			Ported to Linux 2.5.
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *			Minor fixes for 2.6.
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *			Support for sysfs included.
+ */
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/i2o.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif				// CONFIG_MTRR
+
+/* Module internal functions from other sources */
+extern struct i2o_controller *i2o_iop_alloc(void);
+extern void i2o_iop_free(struct i2o_controller *);
+
+extern int i2o_iop_add(struct i2o_controller *);
+extern void i2o_iop_remove(struct i2o_controller *);
+
+extern int i2o_driver_dispatch(struct i2o_controller *, u32,
+			       struct i2o_message *);
+
+/* PCI device id table for all I2O controllers */
+static struct pci_device_id __devinitdata i2o_pci_ids[] = {
+	{PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
+	{PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},
+	{0}
+};
+
+/**
+ *	i2o_dma_realloc - Realloc DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: pointer to a i2o_dma struct DMA buffer
+ *	@len: new length of memory
+ *	@gfp_mask: GFP mask
+ *
+ *	If there was something allocated in the addr, free it first. If len > 0
+ *	than try to allocate it and write the addresses back to the addr
+ *	structure. If len == 0 set the virtual address to NULL.
+ *
+ *	Returns the 0 on success or negative error code on failure.
+ */
+int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len,
+		    unsigned int gfp_mask)
+{
+	i2o_dma_free(dev, addr);
+
+	if (len)
+		return i2o_dma_alloc(dev, addr, len, gfp_mask);
+
+	return 0;
+};
+
+/**
+ *	i2o_pci_free - Frees the DMA memory for the I2O controller
+ *	@c: I2O controller to free
+ *
+ *	Remove all allocated DMA memory and unmap memory IO regions. If MTRR
+ *	is enabled, also remove it again.
+ */
+static void __devexit i2o_pci_free(struct i2o_controller *c)
+{
+	struct device *dev;
+
+	dev = &c->pdev->dev;
+
+	i2o_dma_free(dev, &c->out_queue);
+	i2o_dma_free(dev, &c->status_block);
+	if (c->lct)
+		kfree(c->lct);
+	i2o_dma_free(dev, &c->dlct);
+	i2o_dma_free(dev, &c->hrt);
+	i2o_dma_free(dev, &c->status);
+
+#ifdef CONFIG_MTRR
+	if (c->mtrr_reg0 >= 0)
+		mtrr_del(c->mtrr_reg0, 0, 0);
+	if (c->mtrr_reg1 >= 0)
+		mtrr_del(c->mtrr_reg1, 0, 0);
+#endif
+
+	if (c->raptor && c->in_queue.virt)
+		iounmap(c->in_queue.virt);
+
+	if (c->base.virt)
+		iounmap(c->base.virt);
+}
+
+/**
+ *	i2o_pci_alloc - Allocate DMA memory, map IO memory for I2O controller
+ *	@c: I2O controller
+ *
+ *	Allocate DMA memory for a PCI (or in theory AGP) I2O controller. All
+ *	IO mappings are also done here. If MTRR is enabled, also do add memory
+ *	regions here.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __devinit i2o_pci_alloc(struct i2o_controller *c)
+{
+	struct pci_dev *pdev = c->pdev;
+	struct device *dev = &pdev->dev;
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		/* Skip I/O spaces */
+		if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
+			if (!c->base.phys) {
+				c->base.phys = pci_resource_start(pdev, i);
+				c->base.len = pci_resource_len(pdev, i);
+				if (!c->raptor)
+					break;
+			} else {
+				c->in_queue.phys = pci_resource_start(pdev, i);
+				c->in_queue.len = pci_resource_len(pdev, i);
+				break;
+			}
+		}
+	}
+
+	if (i == 6) {
+		printk(KERN_ERR "i2o: I2O controller has no memory regions"
+		       " defined.\n");
+		i2o_pci_free(c);
+		return -EINVAL;
+	}
+
+	/* Map the I2O controller */
+	if (c->raptor) {
+		printk(KERN_INFO "i2o: PCI I2O controller\n");
+		printk(KERN_INFO "     BAR0 at 0x%08lX size=%ld\n",
+		       (unsigned long)c->base.phys, (unsigned long)c->base.len);
+		printk(KERN_INFO "     BAR1 at 0x%08lX size=%ld\n",
+		       (unsigned long)c->in_queue.phys,
+		       (unsigned long)c->in_queue.len);
+	} else
+		printk(KERN_INFO "i2o: PCI I2O controller at %08lX size=%ld\n",
+		       (unsigned long)c->base.phys, (unsigned long)c->base.len);
+
+	c->base.virt = ioremap(c->base.phys, c->base.len);
+	if (!c->base.virt) {
+		printk(KERN_ERR "i2o: Unable to map controller.\n");
+		return -ENOMEM;
+	}
+
+	if (c->raptor) {
+		c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len);
+		if (!c->in_queue.virt) {
+			printk(KERN_ERR "i2o: Unable to map controller.\n");
+			i2o_pci_free(c);
+			return -ENOMEM;
+		}
+	} else
+		c->in_queue = c->base;
+
+	c->irq_mask = c->base.virt + 0x34;
+	c->post_port = c->base.virt + 0x40;
+	c->reply_port = c->base.virt + 0x44;
+
+#ifdef CONFIG_MTRR
+	/* Enable Write Combining MTRR for IOP's memory region */
+	c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len,
+				MTRR_TYPE_WRCOMB, 1);
+	c->mtrr_reg1 = -1;
+
+	if (c->mtrr_reg0 < 0)
+		printk(KERN_WARNING "i2o: could not enable write combining "
+		       "MTRR\n");
+	else
+		printk(KERN_INFO "i2o: using write combining MTRR\n");
+
+	/*
+	 * If it is an INTEL i960 I/O processor then set the first 64K to
+	 * Uncacheable since the region contains the messaging unit which
+	 * shouldn't be cached.
+	 */
+	if ((pdev->vendor == PCI_VENDOR_ID_INTEL ||
+	     pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) {
+		printk(KERN_INFO "i2o: MTRR workaround for Intel i960 processor"
+		       "\n");
+		c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000,
+					MTRR_TYPE_UNCACHABLE, 1);
+
+		if (c->mtrr_reg1 < 0) {
+			printk(KERN_WARNING "i2o_pci: Error in setting "
+			       "MTRR_TYPE_UNCACHABLE\n");
+			mtrr_del(c->mtrr_reg0, c->in_queue.phys,
+				 c->in_queue.len);
+			c->mtrr_reg0 = -1;
+		}
+	}
+#endif
+
+	if (i2o_dma_alloc(dev, &c->status, 4, GFP_KERNEL)) {
+		i2o_pci_free(c);
+		return -ENOMEM;
+	}
+
+	if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt), GFP_KERNEL)) {
+		i2o_pci_free(c);
+		return -ENOMEM;
+	}
+
+	if (i2o_dma_alloc(dev, &c->dlct, 8192, GFP_KERNEL)) {
+		i2o_pci_free(c);
+		return -ENOMEM;
+	}
+
+	if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block),
+			  GFP_KERNEL)) {
+		i2o_pci_free(c);
+		return -ENOMEM;
+	}
+
+	if (i2o_dma_alloc(dev, &c->out_queue, MSG_POOL_SIZE, GFP_KERNEL)) {
+		i2o_pci_free(c);
+		return -ENOMEM;
+	}
+
+	pci_set_drvdata(pdev, c);
+
+	return 0;
+}
+
+/**
+ *	i2o_pci_interrupt - Interrupt handler for I2O controller
+ *	@irq: interrupt line
+ *	@dev_id: pointer to the I2O controller
+ *	@r: pointer to registers
+ *
+ *	Handle an interrupt from a PCI based I2O controller. This turns out
+ *	to be rather simple. We keep the controller pointer in the cookie.
+ */
+static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
+{
+	struct i2o_controller *c = dev_id;
+	struct device *dev = &c->pdev->dev;
+	struct i2o_message *m;
+	u32 mv;
+	u32 *msg;
+
+	/*
+	 * Old 960 steppings had a bug in the I2O unit that caused
+	 * the queue to appear empty when it wasn't.
+	 */
+	mv = I2O_REPLY_READ32(c);
+	if (mv == I2O_QUEUE_EMPTY) {
+		mv = I2O_REPLY_READ32(c);
+		if (unlikely(mv == I2O_QUEUE_EMPTY)) {
+			return IRQ_NONE;
+		} else
+			pr_debug("960 bug detected\n");
+	}
+
+	while (mv != I2O_QUEUE_EMPTY) {
+		/*
+		 * Map the message from the page frame map to kernel virtual.
+		 * Because bus_to_virt is deprecated, we have calculate the
+		 * location by ourself!
+		 */
+		m = (struct i2o_message *)(mv -
+					   (unsigned long)c->out_queue.phys +
+					   (unsigned long)c->out_queue.virt);
+
+		msg = (u32 *) m;
+
+		/*
+		 *      Ensure this message is seen coherently but cachably by
+		 *      the processor
+		 */
+		dma_sync_single_for_cpu(dev, c->out_queue.phys, MSG_FRAME_SIZE,
+					PCI_DMA_FROMDEVICE);
+
+		/* dispatch it */
+		if (i2o_driver_dispatch(c, mv, m))
+			/* flush it if result != 0 */
+			i2o_flush_reply(c, mv);
+
+		/*
+		 * That 960 bug again...
+		 */
+		mv = I2O_REPLY_READ32(c);
+		if (mv == I2O_QUEUE_EMPTY)
+			mv = I2O_REPLY_READ32(c);
+	}
+	return IRQ_HANDLED;
+}
+
+/**
+ *	i2o_pci_irq_enable - Allocate interrupt for I2O controller
+ *
+ *	Allocate an interrupt for the I2O controller, and activate interrupts
+ *	on the I2O controller.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_pci_irq_enable(struct i2o_controller *c)
+{
+	struct pci_dev *pdev = c->pdev;
+	int rc;
+
+	I2O_IRQ_WRITE32(c, 0xffffffff);
+
+	if (pdev->irq) {
+		rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ,
+				 c->name, c);
+		if (rc < 0) {
+			printk(KERN_ERR "%s: unable to allocate interrupt %d."
+			       "\n", c->name, pdev->irq);
+			return rc;
+		}
+	}
+
+	I2O_IRQ_WRITE32(c, 0x00000000);
+
+	printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq);
+
+	return 0;
+}
+
+/**
+ *	i2o_pci_irq_disable - Free interrupt for I2O controller
+ *	@c: I2O controller
+ *
+ *	Disable interrupts in I2O controller and then free interrupt.
+ */
+static void i2o_pci_irq_disable(struct i2o_controller *c)
+{
+	I2O_IRQ_WRITE32(c, 0xffffffff);
+
+	if (c->pdev->irq > 0)
+		free_irq(c->pdev->irq, c);
+}
+
+/**
+ *	i2o_pci_probe - Probe the PCI device for an I2O controller
+ *	@dev: PCI device to test
+ *	@id: id which matched with the PCI device id table
+ *
+ *	Probe the PCI device for any device which is a memory of the
+ *	Intelligent, I2O class or an Adaptec Zero Channel Controller. We
+ *	attempt to set up each such device and register it with the core.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __devinit i2o_pci_probe(struct pci_dev *pdev,
+				   const struct pci_device_id *id)
+{
+	struct i2o_controller *c;
+	int rc;
+
+	printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
+
+	if ((pdev->class & 0xff) > 1) {
+		printk(KERN_WARNING "i2o: I2O controller found but does not "
+		       "support I2O 1.5 (skipping).\n");
+		return -ENODEV;
+	}
+
+	if ((rc = pci_enable_device(pdev))) {
+		printk(KERN_WARNING "i2o: I2O controller found but could not be"
+		       " enabled.\n");
+		return rc;
+	}
+
+	printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n",
+	       pdev->bus->number, pdev->devfn);
+
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+		printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No "
+		       "suitable DMA available!\n", pdev->bus->number,
+		       pdev->devfn);
+		rc = -ENODEV;
+		goto disable;
+	}
+
+	pci_set_master(pdev);
+
+	c = i2o_iop_alloc();
+	if (IS_ERR(c)) {
+		printk(KERN_ERR "i2o: memory for I2O controller could not be "
+		       "allocated\n");
+		rc = PTR_ERR(c);
+		goto disable;
+	}
+
+	c->pdev = pdev;
+	c->device = pdev->dev;
+
+	/* Cards that fall apart if you hit them with large I/O loads... */
+	if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
+		c->short_req = 1;
+		printk(KERN_INFO "i2o: Symbios FC920 workarounds activated.\n");
+	}
+
+	if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) {
+		c->promise = 1;
+		printk(KERN_INFO "i2o: Promise workarounds activated.\n");
+	}
+
+	/* Cards that go bananas if you quiesce them before you reset them. */
+	if (pdev->vendor == PCI_VENDOR_ID_DPT) {
+		c->no_quiesce = 1;
+		if (pdev->device == 0xa511)
+			c->raptor = 1;
+	}
+
+	if ((rc = i2o_pci_alloc(c))) {
+		printk(KERN_ERR "i2o: DMA / IO allocation for I2O controller "
+		       " failed\n");
+		goto free_controller;
+	}
+
+	if (i2o_pci_irq_enable(c)) {
+		printk(KERN_ERR "i2o: unable to enable interrupts for I2O "
+		       "controller\n");
+		goto free_pci;
+	}
+
+	if ((rc = i2o_iop_add(c)))
+		goto uninstall;
+
+	return 0;
+
+      uninstall:
+	i2o_pci_irq_disable(c);
+
+      free_pci:
+	i2o_pci_free(c);
+
+      free_controller:
+	i2o_iop_free(c);
+
+      disable:
+	pci_disable_device(pdev);
+
+	return rc;
+}
+
+/**
+ *	i2o_pci_remove - Removes a I2O controller from the system
+ *	pdev: I2O controller which should be removed
+ *
+ *	Reset the I2O controller, disable interrupts and remove all allocated
+ *	resources.
+ */
+static void __devexit i2o_pci_remove(struct pci_dev *pdev)
+{
+	struct i2o_controller *c;
+	c = pci_get_drvdata(pdev);
+
+	i2o_iop_remove(c);
+	i2o_pci_irq_disable(c);
+	i2o_pci_free(c);
+
+	printk(KERN_INFO "%s: Controller removed.\n", c->name);
+
+	i2o_iop_free(c);
+	pci_disable_device(pdev);
+};
+
+/* PCI driver for I2O controller */
+static struct pci_driver i2o_pci_driver = {
+	.name = "I2O controller",
+	.id_table = i2o_pci_ids,
+	.probe = i2o_pci_probe,
+	.remove = __devexit_p(i2o_pci_remove),
+};
+
+/**
+ *	i2o_pci_init - registers I2O PCI driver in PCI subsystem
+ *
+ *	Returns > 0 on success or negative error code on failure.
+ */
+int __init i2o_pci_init(void)
+{
+	return pci_register_driver(&i2o_pci_driver);
+};
+
+/**
+ *	i2o_pci_exit - unregisters I2O PCI driver from PCI subsystem
+ */
+void __exit i2o_pci_exit(void)
+{
+	pci_unregister_driver(&i2o_pci_driver);
+};
+
+EXPORT_SYMBOL(i2o_dma_realloc);
diff -Nru a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
--- a/drivers/misc/ibmasm/module.c	2004-05-14 05:00:50 -07:00
+++ b/drivers/misc/ibmasm/module.c	2004-08-24 02:08:34 -07:00
@@ -62,10 +62,17 @@
 	int result = -ENOMEM;
 	struct service_processor *sp;
 
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR "%s: can't enable PCI device at %s\n",
+			DRIVER_NAME, pci_name(pdev));
+		return -ENODEV;
+	}
+
 	sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL);
 	if (sp == NULL) {
 		dev_err(&pdev->dev, "Failed to allocate memory\n");
-		return result;
+		result = -ENOMEM;
+		goto error_kmalloc;
 	}
 	memset(sp, 0, sizeof(struct service_processor));
 
@@ -148,6 +155,8 @@
 	ibmasm_event_buffer_exit(sp);
 error_eventbuffer:
 	kfree(sp);
+error_kmalloc:
+	pci_disable_device(pdev);
 
 	return result;
 }
@@ -166,6 +175,7 @@
 	iounmap(sp->base_address);
 	ibmasm_event_buffer_exit(sp);
 	kfree(sp);
+	pci_disable_device(pdev);
 }
 
 static struct pci_device_id ibmasm_pci_table[] =
diff -Nru a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
--- a/drivers/mtd/chips/jedec_probe.c	2004-07-15 10:31:47 -07:00
+++ b/drivers/mtd/chips/jedec_probe.c	2004-08-25 02:01:59 -07:00
@@ -29,6 +29,7 @@
 #define MANUFACTURER_AMD	0x0001
 #define MANUFACTURER_ATMEL	0x001f
 #define MANUFACTURER_FUJITSU	0x0004
+#define MANUFACTURER_HYUNDAI	0x00AD
 #define MANUFACTURER_INTEL	0x0089
 #define MANUFACTURER_MACRONIX	0x00C2
 #define MANUFACTURER_PMC	0x009D
@@ -56,6 +57,7 @@
 #define AM29F040	0x00A4
 #define AM29LV040B	0x004F
 #define AM29F032B	0x0041
+#define AM29F002T	0x00B0
 
 /* Atmel */
 #define AT49BV512	0x0003
@@ -77,6 +79,8 @@
 #define MBM29LV400TC	0x22B9
 #define MBM29LV400BC	0x22BA
 
+/* Hyundai */
+#define HY29F002T	0x00B0
 
 /* Intel */
 #define I28F004B3T	0x00d4
@@ -106,6 +110,7 @@
 #define MX29LV160T	0x22C4
 #define MX29LV160B	0x2249
 #define MX29F016	0x00AD
+#define MX29F002T	0x00B0
 #define MX29F004T	0x0045
 #define MX29F004B	0x0046
 
@@ -507,6 +512,17 @@
 			ERASEINFO(0x10000,8),
 		}
 	}, {
+		mfr_id: MANUFACTURER_AMD,
+		dev_id: AM29F002T,
+		name: "AMD AM29F002T",
+		DevSize: SIZE_256KiB,
+		NumEraseRegions: 4,
+		regions: {ERASEINFO(0x10000,3),
+			  ERASEINFO(0x08000,1),
+			  ERASEINFO(0x02000,2),
+			  ERASEINFO(0x04000,1)
+		}
+	}, {
 		.mfr_id		= MANUFACTURER_ATMEL,
 		.dev_id		= AT49BV512,
 		.name		= "Atmel AT49BV512",
@@ -752,6 +768,17 @@
 			ERASEINFO(0x04000,1)
 		}
 	}, {
+		mfr_id: MANUFACTURER_HYUNDAI,
+		dev_id: HY29F002T,
+		name: "Hyundai HY29F002T",
+		DevSize: SIZE_256KiB,
+		NumEraseRegions: 4,
+		regions: {ERASEINFO(0x10000,3),
+			  ERASEINFO(0x08000,1),
+			  ERASEINFO(0x02000,2),
+			  ERASEINFO(0x04000,1)
+		}
+	}, {
 		.mfr_id		= MANUFACTURER_INTEL,
 		.dev_id		= I28F004B3B,
 		.name		= "Intel 28F004B3B",
@@ -1135,6 +1162,17 @@
 			ERASEINFO(0x10000,7),
 		}
 	}, {
+		mfr_id: MANUFACTURER_MACRONIX,
+		dev_id: MX29F002T,
+		name: "Macronix MX29F002T",
+		DevSize: SIZE_256KiB,
+		NumEraseRegions: 4,
+		regions: {ERASEINFO(0x10000,3),
+			  ERASEINFO(0x08000,1),
+			  ERASEINFO(0x02000,2),
+			  ERASEINFO(0x04000,1)
+		}
+	}, {
 		.mfr_id		= MANUFACTURER_PMC,
 		.dev_id		= PM49FL002,
 		.name		= "PMC Pm49FL002",
@@ -1570,7 +1608,7 @@
 			ERASEINFO(0x02000, 2),
 			ERASEINFO(0x04000, 1),
 		}
-	} 
+	}
 };
 
 
diff -Nru a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
--- a/drivers/mtd/maps/edb7312.c	2004-07-15 10:31:47 -07:00
+++ b/drivers/mtd/maps/edb7312.c	2004-08-25 18:45:25 -07:00
@@ -71,14 +71,14 @@
 
 #endif
 
-static int                   mtd_parts_nb = 0;
-static struct mtd_partition *mtd_parts    = 0;
+static int mtd_parts_nb;
+static struct mtd_partition *mtd_parts;
 
 int __init init_edb7312nor(void)
 {
 	static const char *rom_probe_types[] = PROBETYPES;
 	const char **type;
-	const char *part_type = 0;
+	const char *part_type = NULL;
 
        	printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", 
 	       WINDOW_SIZE, WINDOW_ADDR);
@@ -92,7 +92,7 @@
 	
 	simple_map_init(&edb7312nor_map);
 
-	mymtd = 0;
+	mymtd = NULL;
 	type = rom_probe_types;
 	for(; !mymtd && *type; type++) {
 		mymtd = do_map_probe(*type, &edb7312nor_map);
diff -Nru a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
--- a/drivers/mtd/maps/impa7.c	2004-07-15 10:31:47 -07:00
+++ b/drivers/mtd/maps/impa7.c	2004-08-25 18:45:32 -07:00
@@ -77,7 +77,7 @@
 {
 	static const char *rom_probe_types[] = PROBETYPES;
 	const char **type;
-	const char *part_type = 0;
+	const char *part_type = NULL;
 	int i;
 	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
@@ -99,7 +99,7 @@
 		}
 		simple_map_init(&impa7_map[i]);
 
-		impa7_mtd[i] = 0;
+		impa7_mtd[i] = NULL;
 		type = rom_probe_types;
 		for(; !impa7_mtd[i] && *type; type++) {
 			impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]);
diff -Nru a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
--- a/drivers/mtd/nftlmount.c	2004-07-15 10:26:47 -07:00
+++ b/drivers/mtd/nftlmount.c	2004-08-25 18:54:37 -07:00
@@ -269,7 +269,8 @@
 static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, 
 			      int check_oob)
 {
-	int i, retlen;
+	int i;
+	size_t retlen;
 	u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
 
 	for (i = 0; i < len; i += SECTORSIZE) {
@@ -366,7 +367,8 @@
 {
 	unsigned int block, i, status;
 	struct nftl_bci bci;
-	int sectors_per_block, retlen;
+	int sectors_per_block;
+	size_t retlen;
 
 	sectors_per_block = nftl->EraseSize / SECTORSIZE;
 	block = first_block;
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	2004-07-08 15:52:55 -07:00
+++ b/drivers/net/8139too.c	2004-08-24 19:18:37 -07:00
@@ -593,6 +593,7 @@
 	int time_to_die;
 	struct mii_if_info mii;
 	unsigned int regs_len;
+	unsigned long fifo_copy_timeout;
 };
 
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
@@ -1927,6 +1928,24 @@
 }
 #endif
 
+static void rtl8139_isr_ack(struct rtl8139_private *tp)
+{
+	void *ioaddr = tp->mmio_addr;
+	u16 status;
+
+	status = RTL_R16 (IntrStatus) & RxAckBits;
+
+	/* Clear out errors and receive interrupts */
+	if (likely(status != 0)) {
+		if (unlikely(status & (RxFIFOOver | RxOverflow))) {
+			tp->stats.rx_errors++;
+			if (status & RxFIFOOver)
+				tp->stats.rx_fifo_errors++;
+		}
+		RTL_W16_F (IntrStatus, RxAckBits);
+	}
+}
+
 static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 		      int budget)
 {
@@ -1934,9 +1953,10 @@
 	int received = 0;
 	unsigned char *rx_ring = tp->rx_ring;
 	unsigned int cur_rx = tp->cur_rx;
+	unsigned int rx_size = 0;
 
 	DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
-		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+		 " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx,
 		 RTL_R16 (RxBufAddr),
 		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
 
@@ -1944,10 +1964,8 @@
 	       && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
 		u32 ring_offset = cur_rx % RX_BUF_LEN;
 		u32 rx_status;
-		unsigned int rx_size;
 		unsigned int pkt_size;
 		struct sk_buff *skb;
-		u16 status;
 
 		rmb();
 
@@ -1976,10 +1994,24 @@
 		 * since EarlyRx is disabled.
 		 */
 		if (unlikely(rx_size == 0xfff0)) {
+			if (!tp->fifo_copy_timeout)
+				tp->fifo_copy_timeout = jiffies + 2;
+			else if (time_after(jiffies, tp->fifo_copy_timeout)) {
+				DPRINTK ("%s: hung FIFO. Reset.", dev->name);
+				rx_size = 0;
+				goto no_early_rx;
+			}
+			if (netif_msg_intr(tp)) {
+				printk(KERN_DEBUG "%s: fifo copy in progress.",
+				       dev->name);
+			}
 			tp->xstats.early_rx++;
-			goto done;
+			break;
 		}
 
+no_early_rx:
+		tp->fifo_copy_timeout = 0;
+
 		/* If Rx err or invalid rx_size/rx_status received
 		 * (which happens if we get lost in the ring),
 		 * Rx process gets reset, so we abort any further
@@ -1989,7 +2021,8 @@
 			     (rx_size < 8) ||
 			     (!(rx_status & RxStatusOK)))) {
 			rtl8139_rx_err (rx_status, dev, tp, ioaddr);
-			return -1;
+			received = -1;
+			goto out;
 		}
 
 		/* Malloc up new buffer, compatible with net-2e. */
@@ -2025,19 +2058,11 @@
 		cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
 		RTL_W16 (RxBufPtr, (u16) (cur_rx - 16));
 
-		/* Clear out errors and receive interrupts */
-		status = RTL_R16 (IntrStatus) & RxAckBits;
-		if (likely(status != 0)) {
-			if (unlikely(status & (RxFIFOOver | RxOverflow))) {
-				tp->stats.rx_errors++;
-				if (status & RxFIFOOver)
-					tp->stats.rx_fifo_errors++;
-			}
-			RTL_W16_F (IntrStatus, RxAckBits);
-		}
+		rtl8139_isr_ack(tp);
 	}
 
- done:
+	if (unlikely(!received || rx_size == 0xfff0))
+		rtl8139_isr_ack(tp);
 
 #if RTL8139_DEBUG > 1
 	DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
@@ -2047,6 +2072,15 @@
 #endif
 
 	tp->cur_rx = cur_rx;
+
+	/*
+	 * The receive buffer should be mostly empty.
+	 * Tell NAPI to reenable the Rx irq.
+	 */
+	if (tp->fifo_copy_timeout)
+		received = budget;
+
+out:
 	return received;
 }
 
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	2004-08-23 01:43:07 -07:00
+++ b/drivers/net/Kconfig	2004-08-24 19:18:36 -07:00
@@ -1752,7 +1752,7 @@
 	  If you have a VIA "Velocity" based network card say Y here.
 
 	  To compile this driver as a module, choose M here. The module
-	  will be called via-rhine.
+	  will be called via-velocity.
 
 config LAN_SAA9730
 	bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
@@ -2046,8 +2046,20 @@
 
 config R8169_NAPI
 	bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)"
-	depends on R8169 && EXPERIMENTAL 
+	depends on R8169 && EXPERIMENTAL
+	help
+	  NAPI is a new driver API designed to reduce CPU and interrupt load
+	  when the driver is receiving lots of packets from the card. It is
+	  still somewhat experimental and thus not yet enabled by default.
+
+	  If your estimated Rx load is 10kpps or more, or if the card will be
+	  deployed on potentially unfriendly networks (e.g. in a firewall),
+	  then say Y here.
+
+	  See <file:Documentation/networking/NAPI_HOWTO.txt> for more
+	  information.
 
+	  If in doubt, say N.
 
 config SK98LIN
 	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
diff -Nru a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
--- a/drivers/net/amd8111e.c	2004-07-26 11:26:20 -07:00
+++ b/drivers/net/amd8111e.c	2004-08-27 00:02:37 -07:00
@@ -719,7 +719,7 @@
 	return 0;
 }
 
-#if CONFIG_AMD8111E_NAPI 
+#ifdef CONFIG_AMD8111E_NAPI
 /* This function handles the driver receive operation in polling mode */
 static int amd8111e_rx_poll(struct net_device *dev, int * budget)
 {
diff -Nru a/drivers/net/dl2k.h b/drivers/net/dl2k.h
--- a/drivers/net/dl2k.h	2003-07-31 08:59:10 -07:00
+++ b/drivers/net/dl2k.h	2004-08-24 19:18:37 -07:00
@@ -92,7 +92,7 @@
 	EepromCtrl = 0x4a,
 	ExpromAddr = 0x4c,
 	Exprodata = 0x50,
-	WakeEvent0x51,
+	WakeEvent = 0x51,
 	CountDown = 0x54,
 	IntStatusAck = 0x5a,
 	IntEnable = 0x5c,
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	2004-07-28 21:50:10 -07:00
+++ b/drivers/net/e1000/e1000_main.c	2004-08-24 19:18:32 -07:00
@@ -128,8 +128,8 @@
 static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
 static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
 static int e1000_set_mac(struct net_device *netdev, void *p);
-static inline void e1000_irq_disable(struct e1000_adapter *adapter);
-static inline void e1000_irq_enable(struct e1000_adapter *adapter);
+static void e1000_irq_disable(struct e1000_adapter *adapter);
+static void e1000_irq_enable(struct e1000_adapter *adapter);
 static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
 static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
 #ifdef CONFIG_E1000_NAPI
@@ -146,9 +146,9 @@
 void set_ethtool_ops(struct net_device *netdev);
 static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
 static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
-static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
-                                     struct e1000_rx_desc *rx_desc,
-                                     struct sk_buff *skb);
+static void e1000_rx_checksum(struct e1000_adapter *adapter,
+				struct e1000_rx_desc *rx_desc,
+				struct sk_buff *skb);
 static void e1000_tx_timeout(struct net_device *dev);
 static void e1000_tx_timeout_task(struct net_device *dev);
 static void e1000_smartspeed(struct e1000_adapter *adapter);
@@ -2077,7 +2077,7 @@
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_disable(struct e1000_adapter *adapter)
 {
 	atomic_inc(&adapter->irq_sem);
@@ -2091,7 +2091,7 @@
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_enable(struct e1000_adapter *adapter)
 {
 	if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
@@ -2593,7 +2593,7 @@
  * @sk_buff: socket buffer with received data
  **/
 
-static inline void
+static void
 e1000_rx_checksum(struct e1000_adapter *adapter,
                   struct e1000_rx_desc *rx_desc,
                   struct sk_buff *skb)
diff -Nru a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
--- a/drivers/net/e1000/e1000_param.c	2004-07-28 21:50:10 -07:00
+++ b/drivers/net/e1000/e1000_param.c	2004-08-28 15:55:39 -07:00
@@ -212,7 +212,7 @@
 #define MAX_TXABSDELAY            0xFFFF
 #define MIN_TXABSDELAY                 0
 
-#define DEFAULT_ITR                    1
+#define DEFAULT_ITR                 8000
 #define MAX_ITR                   100000
 #define MIN_ITR                      100
 
diff -Nru a/drivers/net/gianfar.c b/drivers/net/gianfar.c
--- a/drivers/net/gianfar.c	2004-08-22 13:57:31 -07:00
+++ b/drivers/net/gianfar.c	2004-08-24 19:18:40 -07:00
@@ -307,8 +307,8 @@
 	/* Print out the device info */
 	printk(KERN_INFO DEVICE_NAME, dev->name);
 	for (idx = 0; idx < 6; idx++)
-		printk(KERN_INFO "%2.2x%c", dev->dev_addr[idx], idx == 5 ? ' ' : ':');
-	printk(KERN_INFO "\n");
+		printk("%2.2x%c", dev->dev_addr[idx], idx == 5 ? ' ' : ':');
+	printk("\n");
 
 	/* Even more device info helps when determining which kernel */
 	/* provided which set of benchmarks.  Since this is global for all */
diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c
--- a/drivers/net/hamachi.c	2004-07-26 11:28:04 -07:00
+++ b/drivers/net/hamachi.c	2004-08-24 19:18:33 -07:00
@@ -559,7 +559,7 @@
 static void hamachi_init_ring(struct net_device *dev);
 static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static inline int hamachi_rx(struct net_device *dev);
+static int hamachi_rx(struct net_device *dev);
 static inline int hamachi_tx(struct net_device *dev);
 static void hamachi_error(struct net_device *dev, int intr_status);
 static int hamachi_close(struct net_device *dev);
diff -Nru a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
--- a/drivers/net/hamradio/dmascc.c	2004-05-10 04:25:56 -07:00
+++ b/drivers/net/hamradio/dmascc.c	2004-08-24 19:18:35 -07:00
@@ -246,8 +246,14 @@
 static struct net_device_stats *scc_get_stats(struct net_device *dev);
 static int scc_set_mac_address(struct net_device *dev, void *sa);
 
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs);
+static inline void tx_on(struct scc_priv *priv);
+static inline void rx_on(struct scc_priv *priv);
+static inline void rx_off(struct scc_priv *priv);
+static void start_timer(struct scc_priv *priv, int t, int r15);
+static inline unsigned char random(void);
+
 static inline void z8530_isr(struct scc_info *info);
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs);
 static void rx_isr(struct scc_priv *priv);
 static void special_condition(struct scc_priv *priv, int rc);
 static void rx_bh(void *arg);
@@ -255,12 +261,6 @@
 static void es_isr(struct scc_priv *priv);
 static void tm_isr(struct scc_priv *priv);
 
-static inline void tx_on(struct scc_priv *priv);
-static inline void rx_on(struct scc_priv *priv);
-static inline void rx_off(struct scc_priv *priv);
-static void start_timer(struct scc_priv *priv, int t, int r15);
-static inline unsigned char random(void);
-
 
 /* Initialization variables */
 
@@ -945,42 +945,115 @@
 }
 
 
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
-  struct scc_info *info = dev_id;
+static inline void tx_on(struct scc_priv *priv) {
+  int i, n;
+  unsigned long flags;
 
-  spin_lock(info->priv[0].register_lock);
-  /* At this point interrupts are enabled, and the interrupt under service
-     is already acknowledged, but masked off.
+  if (priv->param.dma >= 0) {
+    n = (priv->chip == Z85230) ? 3 : 1;
+    /* Program DMA controller */
+    flags = claim_dma_lock();
+    set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
+    set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
+    set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
+    release_dma_lock(flags);
+    /* Enable TX underrun interrupt */
+    write_scc(priv, R15, TxUIE);
+    /* Configure DREQ */
+    if (priv->type == TYPE_TWIN)
+      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+	   priv->card_base + TWIN_DMA_CFG);
+    else
+      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
+    /* Write first byte(s) */
+    spin_lock_irqsave(priv->register_lock, flags);
+    for (i = 0; i < n; i++)
+      write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
+    enable_dma(priv->param.dma);
+    spin_unlock_irqrestore(priv->register_lock, flags);
+  } else {
+    write_scc(priv, R15, TxUIE);
+    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+    tx_isr(priv);
+  }
+  /* Reset EOM latch if we do not have the AUTOEOM feature */
+  if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
+}
 
-     Interrupt processing: We loop until we know that the IRQ line is
-     low. If another positive edge occurs afterwards during the ISR,
-     another interrupt will be triggered by the interrupt controller
-     as soon as the IRQ level is enabled again (see asm/irq.h).
 
-     Bottom-half handlers will be processed after scc_isr(). This is
-     important, since we only have small ringbuffers and want new data
-     to be fetched/delivered immediately. */
+static inline void rx_on(struct scc_priv *priv) {
+  unsigned long flags;
 
-  if (info->priv[0].type == TYPE_TWIN) {
-    int is, card_base = info->priv[0].card_base;
-    while ((is = ~inb(card_base + TWIN_INT_REG)) &
-	   TWIN_INT_MSK) {
-      if (is & TWIN_SCC_MSK) {
-	z8530_isr(info);
-      } else if (is & TWIN_TMR1_MSK) {
-	inb(card_base + TWIN_CLR_TMR1);
-	tm_isr(&info->priv[0]);
-      } else {
-	inb(card_base + TWIN_CLR_TMR2);
-	tm_isr(&info->priv[1]);
-      }
+  /* Clear RX FIFO */
+  while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
+  priv->rx_over = 0;
+  if (priv->param.dma >= 0) {
+    /* Program DMA controller */
+    flags = claim_dma_lock();
+    set_dma_mode(priv->param.dma, DMA_MODE_READ);
+    set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+    set_dma_count(priv->param.dma, BUF_SIZE);
+    release_dma_lock(flags);
+    enable_dma(priv->param.dma);
+    /* Configure PackeTwin DMA */
+    if (priv->type == TYPE_TWIN) {
+      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+	   priv->card_base + TWIN_DMA_CFG);
     }
-  } else z8530_isr(info);
-  spin_unlock(info->priv[0].register_lock);
-  return IRQ_HANDLED;
+    /* Sp. cond. intr. only, ext int enable, RX DMA enable */
+    write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
+	      WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+  } else {
+    /* Reset current frame */
+    priv->rx_ptr = 0;
+    /* Intr. on all Rx characters and Sp. cond., ext int enable */
+    write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+	      WT_FN_RDYFN);
+  }
+  write_scc(priv, R0, ERR_RES);
+  write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+}
+
+
+static inline void rx_off(struct scc_priv *priv) {
+  /* Disable receiver */
+  write_scc(priv, R3, Rx8);
+  /* Disable DREQ / RX interrupt */
+  if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+    outb(0, priv->card_base + TWIN_DMA_CFG);
+  else
+    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+  /* Disable DMA */
+  if (priv->param.dma >= 0) disable_dma(priv->param.dma);
+}
+
+
+static void start_timer(struct scc_priv *priv, int t, int r15) {
+  unsigned long flags;
+
+  outb(priv->tmr_mode, priv->tmr_ctrl);
+  if (t == 0) {
+    tm_isr(priv);
+  } else if (t > 0) {
+    save_flags(flags);
+    cli();
+    outb(t & 0xFF, priv->tmr_cnt);
+    outb((t >> 8) & 0xFF, priv->tmr_cnt);
+    if (priv->type != TYPE_TWIN) {
+      write_scc(priv, R15, r15 | CTSIE);
+      priv->rr0 |= CTS;
+    }
+    restore_flags(flags);
+  }
 }
 
 
+static inline unsigned char random(void) {
+  /* See "Numerical Recipes in C", second edition, p. 284 */
+  rand = rand * 1664525L + 1013904223L;
+  return (unsigned char) (rand >> 24);
+}
+
 static inline void z8530_isr(struct scc_info *info) {
   int is, i = 100;
 
@@ -1009,6 +1082,42 @@
 }
 
 
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
+  struct scc_info *info = dev_id;
+
+  spin_lock(info->priv[0].register_lock);
+  /* At this point interrupts are enabled, and the interrupt under service
+     is already acknowledged, but masked off.
+
+     Interrupt processing: We loop until we know that the IRQ line is
+     low. If another positive edge occurs afterwards during the ISR,
+     another interrupt will be triggered by the interrupt controller
+     as soon as the IRQ level is enabled again (see asm/irq.h).
+
+     Bottom-half handlers will be processed after scc_isr(). This is
+     important, since we only have small ringbuffers and want new data
+     to be fetched/delivered immediately. */
+
+  if (info->priv[0].type == TYPE_TWIN) {
+    int is, card_base = info->priv[0].card_base;
+    while ((is = ~inb(card_base + TWIN_INT_REG)) &
+	   TWIN_INT_MSK) {
+      if (is & TWIN_SCC_MSK) {
+	z8530_isr(info);
+      } else if (is & TWIN_TMR1_MSK) {
+	inb(card_base + TWIN_CLR_TMR1);
+	tm_isr(&info->priv[0]);
+      } else {
+	inb(card_base + TWIN_CLR_TMR2);
+	tm_isr(&info->priv[1]);
+      }
+    }
+  } else z8530_isr(info);
+  spin_unlock(info->priv[0].register_lock);
+  return IRQ_HANDLED;
+}
+
+
 static void rx_isr(struct scc_priv *priv) {
   if (priv->param.dma >= 0) {
     /* Check special condition and perform error reset. See 2.4.7.5. */
@@ -1292,114 +1401,3 @@
     break;
   }
 }
-
-
-static inline void tx_on(struct scc_priv *priv) {
-  int i, n;
-  unsigned long flags;
-
-  if (priv->param.dma >= 0) {
-    n = (priv->chip == Z85230) ? 3 : 1;
-    /* Program DMA controller */
-    flags = claim_dma_lock();
-    set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
-    set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
-    set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
-    release_dma_lock(flags);
-    /* Enable TX underrun interrupt */
-    write_scc(priv, R15, TxUIE);
-    /* Configure DREQ */
-    if (priv->type == TYPE_TWIN)
-      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
-	   priv->card_base + TWIN_DMA_CFG);
-    else
-      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
-    /* Write first byte(s) */
-    spin_lock_irqsave(priv->register_lock, flags);
-    for (i = 0; i < n; i++)
-      write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
-    enable_dma(priv->param.dma);
-    spin_unlock_irqrestore(priv->register_lock, flags);
-  } else {
-    write_scc(priv, R15, TxUIE);
-    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
-    tx_isr(priv);
-  }
-  /* Reset EOM latch if we do not have the AUTOEOM feature */
-  if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
-}
-
-
-static inline void rx_on(struct scc_priv *priv) {
-  unsigned long flags;
-
-  /* Clear RX FIFO */
-  while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
-  priv->rx_over = 0;
-  if (priv->param.dma >= 0) {
-    /* Program DMA controller */
-    flags = claim_dma_lock();
-    set_dma_mode(priv->param.dma, DMA_MODE_READ);
-    set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
-    set_dma_count(priv->param.dma, BUF_SIZE);
-    release_dma_lock(flags);
-    enable_dma(priv->param.dma);
-    /* Configure PackeTwin DMA */
-    if (priv->type == TYPE_TWIN) {
-      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
-	   priv->card_base + TWIN_DMA_CFG);
-    }
-    /* Sp. cond. intr. only, ext int enable, RX DMA enable */
-    write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
-	      WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
-  } else {
-    /* Reset current frame */
-    priv->rx_ptr = 0;
-    /* Intr. on all Rx characters and Sp. cond., ext int enable */
-    write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
-	      WT_FN_RDYFN);
-  }
-  write_scc(priv, R0, ERR_RES);
-  write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
-}
-
-
-static inline void rx_off(struct scc_priv *priv) {
-  /* Disable receiver */
-  write_scc(priv, R3, Rx8);
-  /* Disable DREQ / RX interrupt */
-  if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
-    outb(0, priv->card_base + TWIN_DMA_CFG);
-  else
-    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
-  /* Disable DMA */
-  if (priv->param.dma >= 0) disable_dma(priv->param.dma);
-}
-
-
-static void start_timer(struct scc_priv *priv, int t, int r15) {
-  unsigned long flags;
-
-  outb(priv->tmr_mode, priv->tmr_ctrl);
-  if (t == 0) {
-    tm_isr(priv);
-  } else if (t > 0) {
-    save_flags(flags);
-    cli();
-    outb(t & 0xFF, priv->tmr_cnt);
-    outb((t >> 8) & 0xFF, priv->tmr_cnt);
-    if (priv->type != TYPE_TWIN) {
-      write_scc(priv, R15, r15 | CTSIE);
-      priv->rr0 |= CTS;
-    }
-    restore_flags(flags);
-  }
-}
-
-
-static inline unsigned char random(void) {
-  /* See "Numerical Recipes in C", second edition, p. 284 */
-  rand = rand * 1664525L + 1013904223L;
-  return (unsigned char) (rand >> 24);
-}
-
diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c
--- a/drivers/net/hp100.c	2004-05-20 14:16:23 -07:00
+++ b/drivers/net/hp100.c	2004-08-27 00:02:39 -07:00
@@ -2906,13 +2906,19 @@
 static int __devinit hp100_pci_probe (struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
-	struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));
-	int ioaddr = pci_resource_start(pdev, 0);
+	struct net_device *dev;
+	int ioaddr;
 	u_short pci_command;
 	int err;
-	
-	if (!dev)
-		return -ENOMEM;
+
+	if (pci_enable_device(pdev))
+		return -ENODEV;
+
+	dev = alloc_etherdev(sizeof(struct hp100_private));
+	if (!dev) {
+		err = -ENOMEM;
+		goto out0;
+	}
 
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -2934,7 +2940,7 @@
 		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
 	}
 	
-
+	ioaddr = pci_resource_start(pdev, 0);
 	err = hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pdev);
 	if (err) 
 		goto out1;
@@ -2951,6 +2957,8 @@
 	release_region(dev->base_addr, HP100_REGION_SIZE);
  out1:
 	free_netdev(dev);
+ out0:
+	pci_disable_device(pdev);
 	return err;
 }
 
@@ -2959,6 +2967,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 
 	cleanup_dev(dev);
+	pci_disable_device(pdev);
 }
 
 
diff -Nru a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
--- a/drivers/net/ibm_emac/ibm_emac.h	2004-05-22 10:13:08 -07:00
+++ b/drivers/net/ibm_emac/ibm_emac.h	2004-08-04 08:41:48 -07:00
@@ -228,6 +228,21 @@
 	 (desc & EMAC_BAD_RX_PACKET)
 #endif
 
+/* SoC implementation specific EMAC register defaults */
+#if defined(CONFIG_440GP)
+#define EMAC_RWMR_DEFAULT		0x80009000
+#define EMAC_TMR0_DEFAULT		0x00000000
+#define EMAC_TMR1_DEFAULT		0xf8640000
+#elif defined(CONFIG_440GX)
+#define EMAC_RWMR_DEFAULT		0x1000a200
+#define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_2_32
+#define EMAC_TMR1_DEFAULT		0xa00f0000
+#else
+#define EMAC_RWMR_DEFAULT		0x0f002000
+#define EMAC_TMR0_DEFAULT		0x00000000
+#define EMAC_TMR1_DEFAULT		0x380f0000
+#endif				/* CONFIG_440GP */
+
 /* Revision specific EMAC register defaults */
 #ifdef CONFIG_IBM_EMAC4
 #define EMAC_M1_DEFAULT			(EMAC_M1_BASE | \
@@ -236,7 +251,7 @@
 #define EMAC_RMR_DEFAULT		(EMAC_RMR_BASE | \
 					EMAC_RMR_RFAF_128_2048)
 #define EMAC_TMR0_XMIT			(EMAC_TMR0_GNP0 | \
-					EMAC_TMR0_TFAE_128_2048)
+					EMAC_TMR0_DEFAULT)
 #define EMAC_TRTR_DEFAULT		EMAC_TRTR_1024
 #else				/* !CONFIG_IBM_EMAC4 */
 #define EMAC_M1_DEFAULT			EMAC_M1_BASE
@@ -244,20 +259,5 @@
 #define EMAC_TMR0_XMIT			EMAC_TMR0_GNP0
 #define EMAC_TRTR_DEFAULT		EMAC_TRTR_1600
 #endif				/* CONFIG_IBM_EMAC4 */
-
-/* SoC implementation specific EMAC register defaults */
-#if defined(CONFIG_440GP)
-#define EMAC_RWMR_DEFAULT		0x80009000
-#define EMAC_TMR0_DEFAULT		0x00000000
-#define EMAC_TMR1_DEFAULT		0xf8640000
-#elif defined(CONFIG_440GX)
-#define EMAC_RWMR_DEFAULT		0x1000a200
-#define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_128_2048
-#define EMAC_TMR1_DEFAULT		0x88810000
-#else
-#define EMAC_RWMR_DEFAULT		0x0f002000
-#define EMAC_TMR0_DEFAULT		0x00000000
-#define EMAC_TMR1_DEFAULT		0x380f0000
-#endif				/* CONFIG_440GP */
 
 #endif
diff -Nru a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
--- a/drivers/net/ibm_emac/ibm_emac_core.c	2004-06-04 08:50:36 -07:00
+++ b/drivers/net/ibm_emac/ibm_emac_core.c	2004-08-05 07:35:59 -07:00
@@ -90,23 +90,24 @@
 
 #define RGMII_PRIV(ocpdev) ((struct ibm_ocp_rgmii*)ocp_get_drvdata(ocpdev))
 
-static unsigned int rgmii_enable[] =
-    { RGMII_RTBI, RGMII_RGMII, RGMII_TBI, RGMII_GMII };
+static unsigned int rgmii_enable[] = {
+	RGMII_RTBI,
+	RGMII_RGMII,
+	RGMII_TBI,
+	RGMII_GMII
+};
 
-static unsigned int rgmii_speed_mask[] = { 0,
-	0,
+static unsigned int rgmii_speed_mask[] = {
 	RGMII_MII2_SPDMASK,
 	RGMII_MII3_SPDMASK
 };
 
-static unsigned int rgmii_speed100[] = { 0,
-	0,
+static unsigned int rgmii_speed100[] = {
 	RGMII_MII2_100MB,
 	RGMII_MII3_100MB
 };
 
-static unsigned int rgmii_speed1000[] = { 0,
-	0,
+static unsigned int rgmii_speed1000[] = {
 	RGMII_MII2_1000MB,
 	RGMII_MII3_1000MB
 };
@@ -122,11 +123,21 @@
 	 ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI3)},
 	{ZMII_SMII3, ZMII_RMII3, ZMII_MII3, ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI2)}
 };
-static unsigned int mdi_enable[] =
-    { ZMII_MDI0, ZMII_MDI1, ZMII_MDI2, ZMII_MDI3 };
+
+static unsigned int mdi_enable[] = {
+	ZMII_MDI0,
+	ZMII_MDI1,
+	ZMII_MDI2,
+	ZMII_MDI3
+};
 
 static unsigned int zmii_speed = 0x0;
-static unsigned int zmii_speed100[] = { ZMII_MII0_100MB, ZMII_MII1_100MB };
+static unsigned int zmii_speed100[] = {
+	ZMII_MII0_100MB,
+	ZMII_MII1_100MB,
+	ZMII_MII2_100MB,
+	ZMII_MII3_100MB
+};
 
 /* Since multiple EMACs share MDIO lines in various ways, we need
  * to avoid re-using the same PHY ID in cases where the arch didn't
@@ -367,6 +378,7 @@
 
 int emac_phy_read(struct net_device *dev, int mii_id, int reg)
 {
+	int count;
 	uint32_t stacr;
 	struct ocp_enet_private *fep = dev->priv;
 	emac_t *emacp = fep->emacp;
@@ -385,9 +397,13 @@
 		emacp = fep->emacp;
 	}
 
-	udelay(MDIO_DELAY);
+	count = 0;
+	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+					&& (count++ < MDIO_DELAY))
+		udelay(1);
+	MDIO_DEBUG((" (count was %d)\n", count));
 
-	if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) {
+	if ((stacr & EMAC_STACR_OC) == 0) {
 		printk(KERN_WARNING "%s: PHY read timeout #1!\n", dev->name);
 		return -1;
 	}
@@ -398,8 +414,11 @@
 
 	out_be32(&emacp->em0stacr, stacr);
 
-	udelay(MDIO_DELAY);
-	stacr = in_be32(&emacp->em0stacr);
+	count = 0;
+	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+					&& (count++ < MDIO_DELAY))
+		udelay(1);
+	MDIO_DEBUG((" (count was %d)\n", count));
 
 	if ((stacr & EMAC_STACR_OC) == 0) {
 		printk(KERN_WARNING "%s: PHY read timeout #2!\n", dev->name);
@@ -419,6 +438,7 @@
 
 void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
 {
+	int count;
 	uint32_t stacr;
 	struct ocp_enet_private *fep = dev->priv;
 	emac_t *emacp = fep->emacp;
@@ -437,9 +457,13 @@
 		emacp = fep->emacp;
 	}
 
-	udelay(MDIO_DELAY);
+	count = 0;
+	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+					&& (count++ < MDIO_DELAY))
+		udelay(1);
+	MDIO_DEBUG((" (count was %d)\n", count));
 
-	if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) {
+	if ((stacr & EMAC_STACR_OC) == 0) {
 		printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
 		return;
 	}
@@ -451,9 +475,12 @@
 
 	out_be32(&emacp->em0stacr, stacr);
 
-	udelay(MDIO_DELAY);
+	while (((stacr = in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0)
+					&& (count++ < 5000))
+		udelay(1);
+	MDIO_DEBUG((" (count was %d)\n", count));
 
-	if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0)
+	if ((stacr & EMAC_STACR_OC) == 0)
 		printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
 
 	/* Check for a write error */
@@ -1940,8 +1967,6 @@
 
 static int __init emac_init(void)
 {
-	int rc;
-
 	printk(KERN_INFO DRV_NAME ": " DRV_DESC ", version " DRV_VERSION "\n");
 	printk(KERN_INFO "Maintained by " DRV_AUTHOR "\n");
 
@@ -1950,13 +1975,8 @@
 		       skb_res);
 		skb_res = 2;
 	}
-	rc = ocp_register_driver(&emac_driver);
-	if (rc < 0) {
-		ocp_unregister_driver(&emac_driver);
-		return -ENODEV;
-	}
 
-	return 0;
+	return ocp_register_driver(&emac_driver);
 }
 
 static void __exit emac_exit(void)
diff -Nru a/drivers/net/ibm_emac/ibm_emac_core.h b/drivers/net/ibm_emac/ibm_emac_core.h
--- a/drivers/net/ibm_emac/ibm_emac_core.h	2004-05-22 10:13:08 -07:00
+++ b/drivers/net/ibm_emac/ibm_emac_core.h	2004-08-05 07:26:55 -07:00
@@ -67,7 +67,7 @@
 #define TX_TIMEOUT		(2*HZ)
 
 /* MDIO latency delay */
-#define MDIO_DELAY		50
+#define MDIO_DELAY		250
 
 /* Power managment shift registers */
 #define IBM_CPM_EMMII	0	/* Shift value for MII */
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c	2004-05-14 19:00:06 -07:00
+++ b/drivers/net/irda/irda-usb.c	2004-08-24 15:10:19 -07:00
@@ -268,7 +268,6 @@
                       speed_bulk_callback, self);
 	urb->transfer_buffer_length = USB_IRDA_HEADER;
 	urb->transfer_flags = URB_ASYNC_UNLINK;
-	urb->timeout = msecs_to_jiffies(100);
 
 	/* Irq disabled -> GFP_ATOMIC */
 	if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
@@ -411,8 +410,6 @@
 	 * after each of our packets that is exact multiple of the frame size.
 	 * This is how the dongle will detect the end of packet - Jean II */
 	urb->transfer_flags |= URB_ZERO_PACKET;
-	/* Timeout need to be shorter than NET watchdog timer */
-	urb->timeout = msecs_to_jiffies(200);
 
 	/* Generate min turn time. FIXME: can we do better than this? */
 	/* Trying to a turnaround time at this level is trying to measure
diff -Nru a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
--- a/drivers/net/ixgb/ixgb_main.c	2004-06-15 21:38:55 -07:00
+++ b/drivers/net/ixgb/ixgb_main.c	2004-08-24 19:18:34 -07:00
@@ -55,6 +55,8 @@
 
 /* Local Function Prototypes */
 
+static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);
+static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);
 int ixgb_up(struct ixgb_adapter *adapter);
 void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
 void ixgb_reset(struct ixgb_adapter *adapter);
@@ -82,10 +84,11 @@
 static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
 static int ixgb_set_mac(struct net_device *netdev, void *p);
 static void ixgb_update_stats(struct ixgb_adapter *adapter);
-static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);
-static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);
 static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
 static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,
+				    struct ixgb_rx_desc *rx_desc,
+				    struct sk_buff *skb);
 #ifdef CONFIG_IXGB_NAPI
 static int ixgb_clean(struct net_device *netdev, int *budget);
 static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
@@ -95,9 +98,6 @@
 #endif
 static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
 static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
-static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,
-				    struct ixgb_rx_desc *rx_desc,
-				    struct sk_buff *skb);
 static void ixgb_tx_timeout(struct net_device *dev);
 static void ixgb_tx_timeout_task(struct net_device *dev);
 static void ixgb_vlan_rx_register(struct net_device *netdev,
@@ -185,6 +185,34 @@
 
 module_exit(ixgb_exit_module);
 
+/**
+ * ixgb_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+
+static inline void ixgb_irq_disable(struct ixgb_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+	IXGB_WRITE_FLUSH(&adapter->hw);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+/**
+ * ixgb_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+
+static inline void ixgb_irq_enable(struct ixgb_adapter *adapter)
+{
+	if (atomic_dec_and_test(&adapter->irq_sem)) {
+		IXGB_WRITE_REG(&adapter->hw, IMS,
+			       IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
+			       IXGB_INT_RXO | IXGB_INT_LSC);
+		IXGB_WRITE_FLUSH(&adapter->hw);
+	}
+}
+
 int ixgb_up(struct ixgb_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -1550,34 +1578,6 @@
 	adapter->net_stats.tx_window_errors = 0;
 }
 
-/**
- * ixgb_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-
-static inline void ixgb_irq_disable(struct ixgb_adapter *adapter)
-{
-	atomic_inc(&adapter->irq_sem);
-	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
-	IXGB_WRITE_FLUSH(&adapter->hw);
-	synchronize_irq(adapter->pdev->irq);
-}
-
-/**
- * ixgb_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-
-static inline void ixgb_irq_enable(struct ixgb_adapter *adapter)
-{
-	if (atomic_dec_and_test(&adapter->irq_sem)) {
-		IXGB_WRITE_REG(&adapter->hw, IMS,
-			       IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
-			       IXGB_INT_RXO | IXGB_INT_LSC);
-		IXGB_WRITE_FLUSH(&adapter->hw);
-	}
-}
-
 #define IXGB_MAX_INTR 10
 /**
  * ixgb_intr - Interrupt Handler
@@ -1730,6 +1730,39 @@
 }
 
 /**
+ * ixgb_rx_checksum - Receive Checksum Offload for 82597.
+ * @adapter: board private structure
+ * @rx_desc: receive descriptor
+ * @sk_buff: socket buffer with received data
+ **/
+
+static inline void
+ixgb_rx_checksum(struct ixgb_adapter *adapter,
+		 struct ixgb_rx_desc *rx_desc, struct sk_buff *skb)
+{
+	/* Ignore Checksum bit is set OR
+	 * TCP Checksum has not been calculated
+	 */
+	if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
+	    (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
+		skb->ip_summed = CHECKSUM_NONE;
+		return;
+	}
+
+	/* At this point we know the hardware did the TCP checksum */
+	/* now look at the TCP checksum error bit */
+	if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
+		/* let the stack verify checksum errors */
+		skb->ip_summed = CHECKSUM_NONE;
+		adapter->hw_csum_rx_error++;
+	} else {
+		/* TCP checksum is good */
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		adapter->hw_csum_rx_good++;
+	}
+}
+
+/**
  * ixgb_clean_rx_irq - Send received data up the network stack,
  * @adapter: board private structure
  **/
@@ -1953,39 +1986,6 @@
 	}
 
 	return 0;
-}
-
-/**
- * ixgb_rx_checksum - Receive Checksum Offload for 82597.
- * @adapter: board private structure
- * @rx_desc: receive descriptor
- * @sk_buff: socket buffer with received data
- **/
-
-static inline void
-ixgb_rx_checksum(struct ixgb_adapter *adapter,
-		 struct ixgb_rx_desc *rx_desc, struct sk_buff *skb)
-{
-	/* Ignore Checksum bit is set OR 
-	 * TCP Checksum has not been calculated 
-	 */
-	if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
-	    (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
-		skb->ip_summed = CHECKSUM_NONE;
-		return;
-	}
-
-	/* At this point we know the hardware did the TCP checksum */
-	/* now look at the TCP checksum error bit */
-	if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
-		/* let the stack verify checksum errors */
-		skb->ip_summed = CHECKSUM_NONE;
-		adapter->hw_csum_rx_error++;
-	} else {
-		/* TCP checksum is good */
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		adapter->hw_csum_rx_good++;
-	}
 }
 
 /**
diff -Nru a/drivers/net/rrunner.c b/drivers/net/rrunner.c
--- a/drivers/net/rrunner.c	2004-07-13 06:29:35 -07:00
+++ b/drivers/net/rrunner.c	2004-08-24 19:18:33 -07:00
@@ -1139,6 +1139,49 @@
 	return IRQ_HANDLED;
 }
 
+static inline void rr_raz_tx(struct rr_private *rrpriv,
+			     struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; i < TX_RING_ENTRIES; i++) {
+		struct sk_buff *skb = rrpriv->tx_skbuff[i];
+
+		if (skb) {
+			struct tx_desc *desc = &(rrpriv->tx_ring[i]);
+
+	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
+				skb->len, PCI_DMA_TODEVICE);
+			desc->size = 0;
+			set_rraddr(&desc->addr, 0);
+			dev_kfree_skb(skb);
+			rrpriv->tx_skbuff[i] = NULL;
+		}
+	}
+}
+
+
+static inline void rr_raz_rx(struct rr_private *rrpriv,
+			     struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; i < RX_RING_ENTRIES; i++) {
+		struct sk_buff *skb = rrpriv->rx_skbuff[i];
+
+		if (skb) {
+			struct rx_desc *desc = &(rrpriv->rx_ring[i]);
+
+	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
+				dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
+			desc->size = 0;
+			set_rraddr(&desc->addr, 0);
+			dev_kfree_skb(skb);
+			rrpriv->rx_skbuff[i] = NULL;
+		}
+	}
+}
+
 static void rr_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
@@ -1253,49 +1296,6 @@
 	return ecode;
 }
 
-
-static inline void rr_raz_tx(struct rr_private *rrpriv, 
-			     struct net_device *dev)
-{
-	int i;
-
-	for (i = 0; i < TX_RING_ENTRIES; i++) {
-		struct sk_buff *skb = rrpriv->tx_skbuff[i];
-
-		if (skb) {
-			struct tx_desc *desc = &(rrpriv->tx_ring[i]);
-
-	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, 
-				skb->len, PCI_DMA_TODEVICE);
-			desc->size = 0;
-			set_rraddr(&desc->addr, 0);
-			dev_kfree_skb(skb);
-			rrpriv->tx_skbuff[i] = NULL;
-		}
-	}
-}
-
-
-static inline void rr_raz_rx(struct rr_private *rrpriv, 
-			     struct net_device *dev)
-{
-	int i;
-
-	for (i = 0; i < RX_RING_ENTRIES; i++) {
-		struct sk_buff *skb = rrpriv->rx_skbuff[i];
-
-		if (skb) {
-			struct rx_desc *desc = &(rrpriv->rx_ring[i]);
-
-	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, 
-				dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
-			desc->size = 0;
-			set_rraddr(&desc->addr, 0);
-			dev_kfree_skb(skb);
-			rrpriv->rx_skbuff[i] = NULL;
-		}
-	}
-}
 
 static void rr_dump(struct net_device *dev)
 {
diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c
--- a/drivers/net/sis900.c	2004-07-26 11:30:40 -07:00
+++ b/drivers/net/sis900.c	2004-08-25 00:15:20 -07:00
@@ -124,6 +124,7 @@
 	{ "AMD 79C901 HomePNA PHY",		0x0000, 0x6B90, HOME},
 	{ "ICS LAN PHY",			0x0015, 0xF440, LAN },
 	{ "NS 83851 PHY",			0x2000, 0x5C20, MIX },
+	{ "NS 83847 PHY",                       0x2000, 0x5C30, MIX },
 	{ "Realtek RTL8201 PHY",		0x0000, 0x8200, LAN },
 	{ "VIA 6103 PHY",			0x0101, 0x8f20, LAN },
 	{NULL,},
diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
--- a/drivers/net/sk98lin/skge.c	2004-07-02 19:07:10 -07:00
+++ b/drivers/net/sk98lin/skge.c	2004-08-24 19:18:35 -07:00
@@ -110,10 +110,7 @@
 
 #include	<linux/module.h>
 #include	<linux/init.h>
-
-#ifdef CONFIG_PROC_FS
 #include 	<linux/proc_fs.h>
-#endif
 
 #include	"h/skdrv1st.h"
 #include	"h/skdrv2nd.h"
@@ -5113,9 +5110,12 @@
 	if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2)
 		have_second_mac = 1;
 
+	remove_proc_entry(dev->name, pSkRootDir);
 	unregister_netdev(dev);
-	if (have_second_mac)
+	if (have_second_mac) {
+		remove_proc_entry(pAC->dev[1]->name, pSkRootDir);
 		unregister_netdev(pAC->dev[1]);
+	}
 
 	SkGeYellowLED(pAC, pAC->IoBase, 0);
 
@@ -5182,9 +5182,9 @@
 {
 	int error;
 
+#ifdef CONFIG_PROC_FS
 	memcpy(&SK_Root_Dir_entry, BOOT_STRING, sizeof(SK_Root_Dir_entry) - 1);
 
-#ifdef CONFIG_PROC_FS
 	pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net);
 	if (!pSkRootDir) {
 		printk(KERN_WARNING "Unable to create /proc/net/%s",
diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c
--- a/drivers/net/smc9194.c	2004-06-17 22:19:59 -07:00
+++ b/drivers/net/smc9194.c	2004-08-24 19:18:33 -07:00
@@ -1191,133 +1191,6 @@
 	netif_wake_queue(dev);
 }
 
-/*--------------------------------------------------------------------
- .
- . This is the main routine of the driver, to handle the device when
- . it needs some attention.
- .
- . So:
- .   first, save state of the chipset
- .   branch off into routines to handle each case, and acknowledge
- .	    each to the interrupt register
- .   and finally restore state.
- .
- ---------------------------------------------------------------------*/
-
-static irqreturn_t smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
-{
-	struct net_device *dev 	= dev_id;
-	int ioaddr 		= dev->base_addr;
-	struct smc_local *lp = netdev_priv(dev);
-
-	byte	status;
-	word	card_stats;
-	byte	mask;
-	int	timeout;
-	/* state registers */
-	word	saved_bank;
-	word	saved_pointer;
-	int handled = 0;
-
-
-	PRINTK3((CARDNAME": SMC interrupt started \n"));
-
-	saved_bank = inw( ioaddr + BANK_SELECT );
-
-	SMC_SELECT_BANK(2);
-	saved_pointer = inw( ioaddr + POINTER );
-
-	mask = inb( ioaddr + INT_MASK );
-	/* clear all interrupts */
-	outb( 0, ioaddr + INT_MASK );
-
-
-	/* set a timeout value, so I don't stay here forever */
-	timeout = 4;
-
-	PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
-	do {
-		/* read the status flag, and mask it */
-		status = inb( ioaddr + INTERRUPT ) & mask;
-		if (!status )
-			break;
-
-		handled = 1;
-
-		PRINTK3((KERN_WARNING CARDNAME
-			": Handling interrupt status %x \n", status ));
-
-		if (status & IM_RCV_INT) {
-			/* Got a packet(s). */
-			PRINTK2((KERN_WARNING CARDNAME
-				": Receive Interrupt\n"));
-			smc_rcv(dev);
-		} else if (status & IM_TX_INT ) {
-			PRINTK2((KERN_WARNING CARDNAME
-				": TX ERROR handled\n"));
-			smc_tx(dev);
-			outb(IM_TX_INT, ioaddr + INTERRUPT );
-		} else if (status & IM_TX_EMPTY_INT ) {
-			/* update stats */
-			SMC_SELECT_BANK( 0 );
-			card_stats = inw( ioaddr + COUNTER );
-			/* single collisions */
-			lp->stats.collisions += card_stats & 0xF;
-			card_stats >>= 4;
-			/* multiple collisions */
-			lp->stats.collisions += card_stats & 0xF;
-
-			/* these are for when linux supports these statistics */
-
-			SMC_SELECT_BANK( 2 );
-			PRINTK2((KERN_WARNING CARDNAME
-				": TX_BUFFER_EMPTY handled\n"));
-			outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
-			mask &= ~IM_TX_EMPTY_INT;
-			lp->stats.tx_packets += lp->packets_waiting;
-			lp->packets_waiting = 0;
-
-		} else if (status & IM_ALLOC_INT ) {
-			PRINTK2((KERN_DEBUG CARDNAME
-				": Allocation interrupt \n"));
-			/* clear this interrupt so it doesn't happen again */
-			mask &= ~IM_ALLOC_INT;
-
-			smc_hardware_send_packet( dev );
-
-			/* enable xmit interrupts based on this */
-			mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
-
-			/* and let the card send more packets to me */
-			netif_wake_queue(dev);
-			
-			PRINTK2((CARDNAME": Handoff done successfully.\n"));
-		} else if (status & IM_RX_OVRN_INT ) {
-			lp->stats.rx_errors++;
-			lp->stats.rx_fifo_errors++;
-			outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
-		} else if (status & IM_EPH_INT ) {
-			PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
-		} else if (status & IM_ERCV_INT ) {
-			PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
-			outb( IM_ERCV_INT, ioaddr + INTERRUPT );
-		}
-	} while ( timeout -- );
-
-
-	/* restore state register */
-	SMC_SELECT_BANK( 2 );
-	outb( mask, ioaddr + INT_MASK );
-
-	PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
-	outw( saved_pointer, ioaddr + POINTER );
-
-	SMC_SELECT_BANK( saved_bank );
-
-	PRINTK3((CARDNAME ": Interrupt done\n"));
-	return IRQ_RETVAL(handled);
-}
-
 /*-------------------------------------------------------------
  .
  . smc_rcv -  receive a packet from the card
@@ -1508,6 +1381,134 @@
 	outb( saved_packet, ioaddr + PNR_ARR );
 	return;
 }
+
+/*--------------------------------------------------------------------
+ .
+ . This is the main routine of the driver, to handle the device when
+ . it needs some attention.
+ .
+ . So:
+ .   first, save state of the chipset
+ .   branch off into routines to handle each case, and acknowledge
+ .	    each to the interrupt register
+ .   and finally restore state.
+ .
+ ---------------------------------------------------------------------*/
+
+static irqreturn_t smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
+{
+	struct net_device *dev 	= dev_id;
+	int ioaddr 		= dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+
+	byte	status;
+	word	card_stats;
+	byte	mask;
+	int	timeout;
+	/* state registers */
+	word	saved_bank;
+	word	saved_pointer;
+	int handled = 0;
+
+
+	PRINTK3((CARDNAME": SMC interrupt started \n"));
+
+	saved_bank = inw( ioaddr + BANK_SELECT );
+
+	SMC_SELECT_BANK(2);
+	saved_pointer = inw( ioaddr + POINTER );
+
+	mask = inb( ioaddr + INT_MASK );
+	/* clear all interrupts */
+	outb( 0, ioaddr + INT_MASK );
+
+
+	/* set a timeout value, so I don't stay here forever */
+	timeout = 4;
+
+	PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
+	do {
+		/* read the status flag, and mask it */
+		status = inb( ioaddr + INTERRUPT ) & mask;
+		if (!status )
+			break;
+
+		handled = 1;
+
+		PRINTK3((KERN_WARNING CARDNAME
+			": Handling interrupt status %x \n", status ));
+
+		if (status & IM_RCV_INT) {
+			/* Got a packet(s). */
+			PRINTK2((KERN_WARNING CARDNAME
+				": Receive Interrupt\n"));
+			smc_rcv(dev);
+		} else if (status & IM_TX_INT ) {
+			PRINTK2((KERN_WARNING CARDNAME
+				": TX ERROR handled\n"));
+			smc_tx(dev);
+			outb(IM_TX_INT, ioaddr + INTERRUPT );
+		} else if (status & IM_TX_EMPTY_INT ) {
+			/* update stats */
+			SMC_SELECT_BANK( 0 );
+			card_stats = inw( ioaddr + COUNTER );
+			/* single collisions */
+			lp->stats.collisions += card_stats & 0xF;
+			card_stats >>= 4;
+			/* multiple collisions */
+			lp->stats.collisions += card_stats & 0xF;
+
+			/* these are for when linux supports these statistics */
+
+			SMC_SELECT_BANK( 2 );
+			PRINTK2((KERN_WARNING CARDNAME
+				": TX_BUFFER_EMPTY handled\n"));
+			outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
+			mask &= ~IM_TX_EMPTY_INT;
+			lp->stats.tx_packets += lp->packets_waiting;
+			lp->packets_waiting = 0;
+
+		} else if (status & IM_ALLOC_INT ) {
+			PRINTK2((KERN_DEBUG CARDNAME
+				": Allocation interrupt \n"));
+			/* clear this interrupt so it doesn't happen again */
+			mask &= ~IM_ALLOC_INT;
+
+			smc_hardware_send_packet( dev );
+
+			/* enable xmit interrupts based on this */
+			mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
+
+			/* and let the card send more packets to me */
+			netif_wake_queue(dev);
+
+			PRINTK2((CARDNAME": Handoff done successfully.\n"));
+		} else if (status & IM_RX_OVRN_INT ) {
+			lp->stats.rx_errors++;
+			lp->stats.rx_fifo_errors++;
+			outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
+		} else if (status & IM_EPH_INT ) {
+			PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
+		} else if (status & IM_ERCV_INT ) {
+			PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
+			outb( IM_ERCV_INT, ioaddr + INTERRUPT );
+		}
+	} while ( timeout -- );
+
+
+	/* restore state register */
+	SMC_SELECT_BANK( 2 );
+	outb( mask, ioaddr + INT_MASK );
+
+	PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
+	outw( saved_pointer, ioaddr + POINTER );
+
+	SMC_SELECT_BANK( saved_bank );
+
+	PRINTK3((CARDNAME ": Interrupt done\n"));
+	return IRQ_RETVAL(handled);
+}
+
 
 /*----------------------------------------------------
  . smc_close
diff -Nru a/drivers/net/smc91x.c b/drivers/net/smc91x.c
--- a/drivers/net/smc91x.c	2004-07-10 06:38:33 -07:00
+++ b/drivers/net/smc91x.c	2004-08-27 16:35:26 -07:00
@@ -2154,10 +2154,12 @@
 static int __init smc_init(void)
 {
 #ifdef MODULE
+#ifdef CONFIG_ISA
 	if (io == -1)
 		printk(KERN_WARNING 
 			"%s: You shouldn't use auto-probing with insmod!\n",
 			CARDNAME);
+#endif
 #endif
 
 	return driver_register(&smc_driver);
diff -Nru a/drivers/net/smc91x.h b/drivers/net/smc91x.h
--- a/drivers/net/smc91x.h	2004-06-23 06:49:56 -07:00
+++ b/drivers/net/smc91x.h	2004-08-27 13:04:55 -07:00
@@ -809,9 +809,10 @@
 	do {								\
 		char *__ptr = (p);					\
 		int __len = (l);					\
-		if (__len >= 2 && (long)__ptr & 2) {			\
+		if (__len >= 2 && (unsigned long)__ptr & 2) {		\
 			__len -= 2;					\
-			SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\
+			SMC_outw( *(u16 *)__ptr, ioaddr, DATA_REG );	\
+			__ptr += 2;					\
 		}							\
 		SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2);	\
 		if (__len & 2) {					\
@@ -823,7 +824,7 @@
 	do {								\
 		char *__ptr = (p);					\
 		int __len = (l);					\
-		if ((long)__ptr & 2) {					\
+		if ((unsigned long)__ptr & 2) {				\
 			/*						\
 			 * We want 32bit alignment here.		\
 			 * Since some buses perform a full 32bit	\
@@ -831,7 +832,7 @@
 			 * SMC_inw() here.  Back both source (on chip	\
 			 * and destination) pointers of 2 bytes.	\
 			 */						\
-			(long)__ptr &= ~2;				\
+			__ptr -= 2;					\
 			__len += 2;					\
 			SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC );	\
 		}							\
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c	2004-07-26 11:30:40 -07:00
+++ b/drivers/net/sundance.c	2004-08-25 10:34:48 -07:00
@@ -879,7 +879,7 @@
 	if (dev->if_port == 0)
 		dev->if_port = np->default_port;
 
-	np->mcastlock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	np->mcastlock = SPIN_LOCK_UNLOCKED;
 
 	set_rx_mode(dev);
 	writew(0, ioaddr + IntrEnable);
diff -Nru a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
--- a/drivers/net/tokenring/ibmtr.c	2004-07-12 01:01:06 -07:00
+++ b/drivers/net/tokenring/ibmtr.c	2004-08-25 10:35:11 -07:00
@@ -895,7 +895,7 @@
 
 	ti->sram_virt &= ~1; /* to reverse what we do in tok_close */
 	/* init the spinlock */
-	ti->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	ti->lock = SPIN_LOCK_UNLOCKED;
 	init_timer(&ti->tr_timer);
 	
 	i = tok_init_card(dev);
diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
--- a/drivers/net/tulip/de4x5.c	2004-07-13 06:29:35 -07:00
+++ b/drivers/net/tulip/de4x5.c	2004-08-25 10:34:58 -07:00
@@ -1141,7 +1141,7 @@
 	lp->asBitValid = TRUE;
 	lp->timeout = -1;
 	lp->gendev = gendev;
-	lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	lp->lock = SPIN_LOCK_UNLOCKED;
 	init_timer(&lp->timer);
 	de4x5_parse_params(dev);
 
@@ -1316,7 +1316,7 @@
     ** Re-initialize the DE4X5... 
     */
     status = de4x5_init(dev);
-    lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+    lp->lock = SPIN_LOCK_UNLOCKED;
     lp->state = OPEN;
     de4x5_dbg_open(dev);
     
@@ -2242,8 +2242,13 @@
 		return -ENODEV;
 
 	/* Ok, the device seems to be for us. */
-	if (!(dev = alloc_etherdev (sizeof (struct de4x5_private))))
-		return -ENOMEM;
+	if (pci_enable_device (pdev))
+		return -ENODEV;
+
+	if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) {
+		error = -ENOMEM;
+		goto disable_dev;
+	}
 
 	lp = netdev_priv(dev);
 	lp->bus = PCI;
@@ -2327,6 +2332,8 @@
 	release_region (iobase, DE4X5_PCI_TOTAL_SIZE);
  free_dev:
 	free_netdev (dev);
+ disable_dev:
+	pci_disable_device (pdev);
 	return error;
 }
 
@@ -2341,6 +2348,7 @@
 	unregister_netdev (dev);
 	free_netdev (dev);
 	release_region (iobase, DE4X5_PCI_TOTAL_SIZE);
+	pci_disable_device (pdev);
 }
 
 static struct pci_device_id de4x5_pci_tbl[] = {
diff -Nru a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
--- a/drivers/net/tulip/dmfe.c	2004-07-14 11:26:31 -07:00
+++ b/drivers/net/tulip/dmfe.c	2004-08-24 19:18:33 -07:00
@@ -314,13 +314,13 @@
 static u8 dmfe_sense_speed(struct dmfe_board_info *);
 static void dmfe_process_mode(struct dmfe_board_info *);
 static void dmfe_timer(unsigned long);
+static inline u32 cal_CRC(unsigned char *, unsigned int, u8);
 static void dmfe_rx_packet(struct DEVICE *, struct dmfe_board_info *);
 static void dmfe_free_tx_pkt(struct DEVICE *, struct dmfe_board_info *);
 static void dmfe_reuse_skb(struct dmfe_board_info *, struct sk_buff *);
 static void dmfe_dynamic_reset(struct DEVICE *);
 static void dmfe_free_rxbuffer(struct dmfe_board_info *);
 static void dmfe_init_dm910x(struct DEVICE *);
-static inline u32 cal_CRC(unsigned char *, unsigned int, u8);
 static void dmfe_parse_srom(struct dmfe_board_info *);
 static void dmfe_program_DM9801(struct dmfe_board_info *, int);
 static void dmfe_program_DM9802(struct dmfe_board_info *);
@@ -885,6 +885,20 @@
 
 
 /*
+ *	Calculate the CRC valude of the Rx packet
+ *	flag = 	1 : return the reverse CRC (for the received packet CRC)
+ *		0 : return the normal CRC (for Hash Table index)
+ */
+
+static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
+{
+	u32 crc = crc32(~0, Data, Len);
+	if (flag) crc = ~crc;
+	return crc;
+}
+
+
+/*
  *	Receive the come packet and pass to upper layer
  */
 
@@ -1770,20 +1784,6 @@
 	udelay(1);
 
 	return phy_data;
-}
-
-
-/*
- *	Calculate the CRC valude of the Rx packet
- *	flag = 	1 : return the reverse CRC (for the received packet CRC)
- *		0 : return the normal CRC (for Hash Table index)
- */
-
-static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
-{
-	u32 crc = crc32(~0, Data, Len);
-	if (flag) crc = ~crc;
-	return crc;
 }
 
 
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	2004-08-13 02:15:27 -07:00
+++ b/drivers/net/via-rhine.c	2004-08-24 19:18:35 -07:00
@@ -346,7 +346,7 @@
 	VT6105L		= 0x8A,
 	VT6107		= 0x8C,
 	VTunknown2	= 0x8E,
-	VT6105M		= 0x90,
+	VT6105M		= 0x90,	/* Management adapter */
 };
 
 enum rhine_quirks {
@@ -485,6 +485,7 @@
 	dma_addr_t tx_bufs_dma;
 
 	struct pci_dev *pdev;
+	long pioaddr;
 	struct net_device_stats stats;
 	spinlock_t lock;
 
@@ -593,7 +594,7 @@
 			default:
 				reason = "Unknown";
 			}
-			printk("%s: Woke system up. Reason: %s.\n",
+			printk(KERN_INFO "%s: Woke system up. Reason: %s.\n",
 			       DRV_NAME, reason);
 		}
 	}
@@ -703,7 +704,7 @@
 	long memaddr;
 	long ioaddr;
 	int io_size, phy_id;
-	const char *name, *mname;
+	const char *name;
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -718,41 +719,24 @@
 	phy_id = 0;
 	quirks = 0;
 	name = "Rhine";
-	mname = "unknown";
 	if (pci_rev < VTunknown0) {
 		quirks = rqRhineI;
 		io_size = 128;
-		mname = "VT86C100A";
 	}
 	else if (pci_rev >= VT6102) {
 		quirks = rqWOL | rqForceReset;
 		if (pci_rev < VT6105) {
 			name = "Rhine II";
 			quirks |= rqStatusWBRace;	/* Rhine-II exclusive */
-			if (pci_rev < VT8231)
-				mname = "VT6102";
-			else if (pci_rev < VT8233)
-				mname = "VT8231";
-			else if (pci_rev < VT8235)
-				mname = "VT8233";
-			else if (pci_rev < VT8237)
-				mname = "VT8235";
-			else if (pci_rev < VTunknown1)
-				mname = "VT8237";
 		}
 		else {
-			name = "Rhine III";
 			phy_id = 1;	/* Integrated PHY, phy_id fixed to 1 */
 			if (pci_rev >= VT6105_B0)
 				quirks |= rq6patterns;
-			if (pci_rev < VT6105L)
-				mname = "VT6105";
-			else if (pci_rev < VT6107)
-				mname = "VT6105L";
-			else if (pci_rev < VT6105M)
-				mname = "VT6107";
-			else if (pci_rev >= VT6105M)
-				mname = "Management Adapter VT6105M";
+			if (pci_rev < VT6105M)
+				name = "Rhine III";
+			else
+				name = "Rhine III (Management Adapter)";
 		}
 	}
 
@@ -790,6 +774,11 @@
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
+	rp = netdev_priv(dev);
+	rp->quirks = quirks;
+	rp->pioaddr = pioaddr;
+	rp->pdev = pdev;
+
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc)
 		goto err_out_free_netdev;
@@ -823,8 +812,6 @@
 #endif /* USE_MMIO */
 
 	dev->base_addr = ioaddr;
-	rp = netdev_priv(dev);
-	rp->quirks = quirks;
 
 	/* Get chip registers into a sane state */
 	rhine_power_init(dev);
@@ -846,7 +833,6 @@
 	dev->irq = pdev->irq;
 
 	spin_lock_init(&rp->lock);
-	rp->pdev = pdev;
 	rp->mii_if.dev = dev;
 	rp->mii_if.mdio_read = mdio_read;
 	rp->mii_if.mdio_write = mdio_write;
@@ -874,8 +860,8 @@
 	if (rc)
 		goto err_out_unmap;
 
-	printk(KERN_INFO "%s: VIA %s (%s) at 0x%lx, ",
-	       dev->name, name, mname,
+	printk(KERN_INFO "%s: VIA %s at 0x%lx, ",
+	       dev->name, name,
 #ifdef USE_MMIO
 		memaddr
 #else
@@ -890,7 +876,10 @@
 	pci_set_drvdata(pdev, dev);
 
 	{
+		u16 mii_cmd;
 		int mii_status = mdio_read(dev, phy_id, 1);
+		mii_cmd = mdio_read(dev, phy_id, MII_BMCR) & ~BMCR_ISOLATE;
+		mdio_write(dev, phy_id, MII_BMCR, mii_cmd);
 		if (mii_status != 0xffff && mii_status != 0x0000) {
 			rp->mii_if.advertising = mdio_read(dev, phy_id, 4);
 			printk(KERN_INFO "%s: MII PHY found at address "
@@ -1172,7 +1161,7 @@
 
 	rhine_disable_linkmon(ioaddr, rp->quirks);
 
-	writeb(0, ioaddr + MIICmd);
+	/* rhine_disable_linkmon already cleared MIICmd */
 	writeb(phy_id, ioaddr + MIIPhyAddr);
 	writeb(regnum, ioaddr + MIIRegAddr);
 	writeb(0x40, ioaddr + MIICmd);		/* Trigger read */
@@ -1190,7 +1179,7 @@
 
 	rhine_disable_linkmon(ioaddr, rp->quirks);
 
-	writeb(0, ioaddr + MIICmd);
+	/* rhine_disable_linkmon already cleared MIICmd */
 	writeb(phy_id, ioaddr + MIIPhyAddr);
 	writeb(regnum, ioaddr + MIIRegAddr);
 	writew(value, ioaddr + MIIData);
@@ -1951,11 +1940,70 @@
 
 }
 
+#ifdef CONFIG_PM
+static int rhine_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rhine_private *rp = netdev_priv(dev);
+	unsigned long flags;
+
+	if (!netif_running(dev))
+		return 0;
+
+	netif_device_detach(dev);
+	pci_save_state(pdev, pdev->saved_config_space);
+
+	spin_lock_irqsave(&rp->lock, flags);
+	rhine_shutdown(&pdev->dev);
+	spin_unlock_irqrestore(&rp->lock, flags);
+
+	return 0;
+}
+
+static int rhine_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rhine_private *rp = netdev_priv(dev);
+	unsigned long flags;
+	int ret;
+
+	if (!netif_running(dev))
+		return 0;
+
+	ret = pci_set_power_state(pdev, 0);
+	if (debug > 1)
+		printk(KERN_INFO "%s: Entering power state D0 %s (%d).\n",
+			dev->name, ret ? "failed" : "succeeded", ret);
+
+	pci_restore_state(pdev, pdev->saved_config_space);
+
+	spin_lock_irqsave(&rp->lock, flags);
+#ifdef USE_MMIO
+	enable_mmio(rp->pioaddr, rp->quirks);
+#endif
+	rhine_power_init(dev);
+	free_tbufs(dev);
+	free_rbufs(dev);
+	alloc_tbufs(dev);
+	alloc_rbufs(dev);
+	init_registers(dev);
+	spin_unlock_irqrestore(&rp->lock, flags);
+
+	netif_device_attach(dev);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 static struct pci_driver rhine_driver = {
 	.name		= DRV_NAME,
 	.id_table	= rhine_pci_tbl,
 	.probe		= rhine_init_one,
 	.remove		= __devexit_p(rhine_remove_one),
+#ifdef CONFIG_PM
+	.suspend	= rhine_suspend,
+	.resume		= rhine_resume,
+#endif /* CONFIG_PM */
 	.driver = {
 		.shutdown = rhine_shutdown,
 	}
diff -Nru a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
--- a/drivers/net/via-velocity.c	2004-08-23 01:15:29 -07:00
+++ b/drivers/net/via-velocity.c	2004-08-24 19:18:34 -07:00
@@ -262,6 +262,7 @@
 static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status);
 
 #ifdef CONFIG_PM
+
 static int velocity_suspend(struct pci_dev *pdev, u32 state);
 static int velocity_resume(struct pci_dev *pdev);
 
@@ -270,9 +271,26 @@
 static struct notifier_block velocity_inetaddr_notifier = {
       .notifier_call	= velocity_netdev_event,
 };
-static int velocity_notifier_registered;
 
-#endif				/* CONFIG_PM */
+static spinlock_t velocity_dev_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(velocity_dev_list);
+
+static void velocity_register_notifier(void)
+{
+	register_inetaddr_notifier(&velocity_inetaddr_notifier);
+}
+
+static void velocity_unregister_notifier(void)
+{
+	unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
+}
+
+#else				/* CONFIG_PM */
+
+#define velocity_register_notifier()	do {} while (0)
+#define velocity_unregister_notifier()	do {} while (0)
+
+#endif				/* !CONFIG_PM */
 
 /*
  *	Internal board variants. At the moment we have only one
@@ -327,6 +345,14 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct velocity_info *vptr = dev->priv;
 
+#ifdef CONFIG_PM
+	unsigned long flags;
+
+	spin_lock_irqsave(&velocity_dev_list_lock, flags);
+	if (!list_empty(&velocity_dev_list))
+		list_del(&vptr->list);
+	spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+#endif
 	unregister_netdev(dev);
 	iounmap(vptr->mac_regs);
 	pci_release_regions(pdev);
@@ -782,13 +808,16 @@
 	/* and leave the chip powered down */
 	
 	pci_set_power_state(pdev, 3);
-out:
 #ifdef CONFIG_PM
-	if (ret == 0 && !velocity_notifier_registered) {
-		velocity_notifier_registered = 1;
-		register_inetaddr_notifier(&velocity_inetaddr_notifier);
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&velocity_dev_list_lock, flags);
+		list_add(&vptr->list, &velocity_dev_list);
+		spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
 	}
 #endif
+out:
 	return ret;
 
 err_iounmap:
@@ -843,6 +872,8 @@
 
 	spin_lock_init(&vptr->lock);
 	spin_lock_init(&vptr->xmit_lock);
+
+	INIT_LIST_HEAD(&vptr->list);
 }
 
 /**
@@ -2211,8 +2242,11 @@
 static int __init velocity_init_module(void)
 {
 	int ret;
-	ret = pci_module_init(&velocity_driver);
 
+	velocity_register_notifier();
+	ret = pci_module_init(&velocity_driver);
+	if (ret < 0)
+		velocity_unregister_notifier();
 	return ret;
 }
 
@@ -2227,12 +2261,7 @@
  
 static void __exit velocity_cleanup_module(void)
 {
-#ifdef CONFIG_PM
-	if (velocity_notifier_registered) {
-		unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
-		velocity_notifier_registered = 0;
-	}
-#endif
+	velocity_unregister_notifier();
 	pci_unregister_driver(&velocity_driver);
 }
 
@@ -3252,13 +3281,20 @@
 static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
 {
 	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
-	struct net_device *dev;
-	struct velocity_info *vptr;
 
 	if (ifa) {
-		dev = ifa->ifa_dev->dev;
-		vptr = dev->priv;
-		velocity_get_ip(vptr);
+		struct net_device *dev = ifa->ifa_dev->dev;
+		struct velocity_info *vptr;
+		unsigned long flags;
+
+		spin_lock_irqsave(&velocity_dev_list_lock, flags);
+		list_for_each_entry(vptr, &velocity_dev_list, list) {
+			if (vptr->dev == dev) {
+				velocity_get_ip(vptr);
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
 	}
 	return NOTIFY_DONE;
 }
diff -Nru a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
--- a/drivers/net/via-velocity.h	2004-06-21 12:38:34 -07:00
+++ b/drivers/net/via-velocity.h	2004-08-27 00:02:37 -07:00
@@ -1733,14 +1733,13 @@
 };
 
 struct velocity_info {
-	struct velocity_info *next;
-	struct velocity_info *prev;
+	struct list_head list;
 
 	struct pci_dev *pdev;
 	struct net_device *dev;
 	struct net_device_stats stats;
 
-#if CONFIG_PM
+#ifdef CONFIG_PM
 	u32 pci_state[16];
 #endif
 
diff -Nru a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
--- a/drivers/net/wan/cycx_x25.c	2003-09-11 10:40:53 -07:00
+++ b/drivers/net/wan/cycx_x25.c	2004-08-24 19:18:34 -07:00
@@ -186,7 +186,7 @@
 	    reset_timer(struct net_device *dev);
 
 static u8 bps_to_speed_code(u32 bps);
-static u8 log2(u32 n);
+static u8 cycx_log2(u32 n);
 
 static unsigned dec_to_uint(u8 *str, int len);
 
@@ -263,7 +263,7 @@
 	else
 		card->wandev.mtu = 64;
 
-	cfg.pktlen = log2(card->wandev.mtu);
+	cfg.pktlen = cycx_log2(card->wandev.mtu);
 
 	if (conf->station == WANOPT_DTE) {
 		cfg.locaddr = 3; /* DTE */
@@ -1513,7 +1513,7 @@
 }
 
 /* log base 2 */
-static u8 log2(u32 n)
+static u8 cycx_log2(u32 n)
 {
 	u8 log = 0;
 
diff -Nru a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c
--- a/drivers/net/wan/lmc/lmc_debug.c	2003-05-26 22:01:35 -07:00
+++ b/drivers/net/wan/lmc/lmc_debug.c	2004-08-27 00:02:39 -07:00
@@ -64,7 +64,7 @@
 #endif
 }
 
-inline void lmc_trace(struct net_device *dev, char *msg){
+void lmc_trace(struct net_device *dev, char *msg){
 #ifdef LMC_TRACE
     unsigned long j = jiffies + 3; /* Wait for 50 ms */
 
diff -Nru a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
--- a/drivers/oprofile/buffer_sync.c	2004-06-30 12:54:33 -07:00
+++ b/drivers/oprofile/buffer_sync.c	2004-08-26 23:42:56 -07:00
@@ -32,61 +32,65 @@
 #include "cpu_buffer.h"
 #include "buffer_sync.h"
  
-#define DEFAULT_EXPIRE (HZ / 4)
- 
-static void wq_sync_buffers(void *);
-static DECLARE_WORK(sync_wq, wq_sync_buffers, NULL);
- 
-static struct timer_list sync_timer;
-static void timer_ping(unsigned long data);
-static void sync_cpu_buffers(void);
+static LIST_HEAD(dying_tasks);
+static LIST_HEAD(dead_tasks);
+cpumask_t marked_cpus = CPU_MASK_NONE;
+static spinlock_t task_mortuary = SPIN_LOCK_UNLOCKED;
+void process_task_mortuary(void);
 
- 
-/* We must make sure to process every entry in the CPU buffers
- * before a task got the PF_EXITING flag, otherwise we will hold
- * references to a possibly freed task_struct. We are safe with
- * samples past the PF_EXITING point in do_exit(), because we
- * explicitly check for that in cpu_buffer.c 
+
+/* Take ownership of the task struct and place it on the
+ * list for processing. Only after two full buffer syncs
+ * does the task eventually get freed, because by then
+ * we are sure we will not reference it again.
  */
-static int exit_task_notify(struct notifier_block * self, unsigned long val, void * data)
+static int task_free_notify(struct notifier_block * self, unsigned long val, void * data)
 {
-	sync_cpu_buffers();
-	return 0;
+	struct task_struct * task = (struct task_struct *)data;
+	spin_lock(&task_mortuary);
+	list_add(&task->tasks, &dying_tasks);
+	spin_unlock(&task_mortuary);
+	return NOTIFY_OK;
 }
- 
-/* There are two cases of tasks modifying task->mm->mmap list we
- * must concern ourselves with. First, when a task is about to
- * exit (exit_mmap()), we should process the buffer to deal with
- * any samples in the CPU buffer, before we lose the ->mmap information
- * we need. It is vital to get this case correct, otherwise we can
- * end up trying to access a freed task_struct.
+
+
+/* The task is on its way out. A sync of the buffer means we can catch
+ * any remaining samples for this task.
  */
-static int mm_notify(struct notifier_block * self, unsigned long val, void * data)
+static int task_exit_notify(struct notifier_block * self, unsigned long val, void * data)
 {
-	sync_cpu_buffers();
-	return 0;
+	/* To avoid latency problems, we only process the current CPU,
+	 * hoping that most samples for the task are on this CPU
+	 */
+	sync_buffer(smp_processor_id());
+  	return 0;
 }
 
 
-/* Second, a task may unmap (part of) an executable mmap,
- * so we want to process samples before that happens too. This is merely
- * a QOI issue not a correctness one.
+/* The task is about to try a do_munmap(). We peek at what it's going to
+ * do, and if it's an executable region, process the samples first, so
+ * we don't lose any. This does not have to be exact, it's a QoI issue
+ * only.
  */
 static int munmap_notify(struct notifier_block * self, unsigned long val, void * data)
 {
-	/* Note that we cannot sync the buffers directly, because we might end up
-	 * taking the the mmap_sem that we hold now inside of event_buffer_read()
-	 * on a page fault, whilst holding buffer_sem - deadlock.
-	 *
-	 * This would mean a threaded reader of the event buffer, but we should
-	 * prevent it anyway.
-	 *
-	 * Delaying the work in a context that doesn't hold the mmap_sem means
-	 * that we won't lose samples from other mappings that current() may
-	 * have. Note that either way, we lose any pending samples for what is
-	 * being unmapped.
-	 */
-	schedule_work(&sync_wq);
+	unsigned long addr = (unsigned long)data;
+	struct mm_struct * mm = current->mm;
+	struct vm_area_struct * mpnt;
+
+	down_read(&mm->mmap_sem);
+
+	mpnt = find_vma(mm, addr);
+	if (mpnt && mpnt->vm_file && (mpnt->vm_flags & VM_EXEC)) {
+		up_read(&mm->mmap_sem);
+		/* To avoid latency problems, we only process the current CPU,
+		 * hoping that most samples for the task are on this CPU
+		 */
+		sync_buffer(smp_processor_id());
+		return 0;
+	}
+
+	up_read(&mm->mmap_sem);
 	return 0;
 }
 
@@ -100,7 +104,7 @@
 	if (val != MODULE_STATE_COMING)
 		return 0;
 
-	sync_cpu_buffers();
+	/* FIXME: should we process all CPU buffers ? */
 	down(&buffer_sem);
 	add_event_entry(ESCAPE_CODE);
 	add_event_entry(MODULE_LOADED_CODE);
@@ -110,16 +114,16 @@
 }
 
  
-static struct notifier_block exit_task_nb = {
-	.notifier_call	= exit_task_notify,
+static struct notifier_block task_free_nb = {
+	.notifier_call	= task_free_notify,
 };
 
-static struct notifier_block exec_unmap_nb = {
-	.notifier_call	= munmap_notify,
+static struct notifier_block task_exit_nb = {
+	.notifier_call	= task_exit_notify,
 };
 
-static struct notifier_block exit_mmap_nb = {
-	.notifier_call	= mm_notify,
+static struct notifier_block munmap_nb = {
+	.notifier_call	= munmap_notify,
 };
 
 static struct notifier_block module_load_nb = {
@@ -127,11 +131,12 @@
 };
 
  
-static void end_sync_timer(void)
+static void end_sync(void)
 {
-	del_timer_sync(&sync_timer);
-	/* timer might have queued work, make sure it's completed. */
-	flush_scheduled_work();
+	end_cpu_timers();
+	/* make sure we don't leak task structs */
+	process_task_mortuary();
+	process_task_mortuary();
 }
 
 
@@ -139,18 +144,15 @@
 {
 	int err;
 
-	init_timer(&sync_timer);
-	sync_timer.function = timer_ping;
-	sync_timer.expires = jiffies + DEFAULT_EXPIRE;
-	add_timer(&sync_timer);
+	start_cpu_timers();
 
-	err = profile_event_register(EXIT_TASK, &exit_task_nb);
+	err = task_handoff_register(&task_free_nb);
 	if (err)
 		goto out1;
-	err = profile_event_register(EXIT_MMAP, &exit_mmap_nb);
+	err = profile_event_register(PROFILE_TASK_EXIT, &task_exit_nb);
 	if (err)
 		goto out2;
-	err = profile_event_register(EXEC_UNMAP, &exec_unmap_nb);
+	err = profile_event_register(PROFILE_MUNMAP, &munmap_nb);
 	if (err)
 		goto out3;
 	err = register_module_notifier(&module_load_nb);
@@ -160,13 +162,13 @@
 out:
 	return err;
 out4:
-	profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb);
+	profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
 out3:
-	profile_event_unregister(EXIT_MMAP, &exit_mmap_nb);
+	profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
 out2:
-	profile_event_unregister(EXIT_TASK, &exit_task_nb);
+	task_handoff_unregister(&task_free_nb);
 out1:
-	end_sync_timer();
+	end_sync();
 	goto out;
 }
 
@@ -174,10 +176,10 @@
 void sync_stop(void)
 {
 	unregister_module_notifier(&module_load_nb);
-	profile_event_unregister(EXIT_TASK, &exit_task_nb);
-	profile_event_unregister(EXIT_MMAP, &exit_mmap_nb);
-	profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb);
-	end_sync_timer();
+	profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
+	profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
+	task_handoff_unregister(&task_free_nb);
+	end_sync();
 }
 
  
@@ -417,24 +419,80 @@
 }
 
 
+/* Move tasks along towards death. Any tasks on dead_tasks
+ * will definitely have no remaining references in any
+ * CPU buffers at this point, because we use two lists,
+ * and to have reached the list, it must have gone through
+ * one full sync already.
+ */
+void process_task_mortuary(void)
+{
+	struct list_head * pos;
+	struct list_head * pos2;
+	struct task_struct * task;
+
+	spin_lock(&task_mortuary);
+
+	list_for_each_safe(pos, pos2, &dead_tasks) {
+		task = list_entry(pos, struct task_struct, tasks);
+		list_del(&task->tasks);
+		free_task(task);
+	}
+
+	list_for_each_safe(pos, pos2, &dying_tasks) {
+		task = list_entry(pos, struct task_struct, tasks);
+		list_del(&task->tasks);
+		list_add_tail(&task->tasks, &dead_tasks);
+	}
+
+	spin_unlock(&task_mortuary);
+}
+
+
+static void mark_done(int cpu)
+{
+	int i;
+
+	cpu_set(cpu, marked_cpus);
+
+	for_each_online_cpu(i) {
+		if (!cpu_isset(i, marked_cpus))
+			return;
+	}
+
+	/* All CPUs have been processed at least once,
+	 * we can process the mortuary once
+	 */
+	process_task_mortuary();
+
+	cpus_clear(marked_cpus);
+}
+
+
 /* Sync one of the CPU's buffers into the global event buffer.
  * Here we need to go through each batch of samples punctuated
  * by context switch notes, taking the task's mmap_sem and doing
  * lookup in task->mm->mmap to convert EIP into dcookie/offset
  * value.
  */
-static void sync_buffer(struct oprofile_cpu_buffer * cpu_buf)
+void sync_buffer(int cpu)
 {
+	struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[cpu];
 	struct mm_struct *mm = NULL;
 	struct task_struct * new;
 	unsigned long cookie = 0;
 	int in_kernel = 1;
 	unsigned int i;
+	unsigned long available;
+
+	down(&buffer_sem);
  
+	add_cpu_switch(cpu);
+
 	/* Remember, only we can modify tail_pos */
 
-	unsigned long const available = get_slots(cpu_buf);
-  
+	available = get_slots(cpu_buf);
+
 	for (i=0; i < available; ++i) {
 		struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
  
@@ -462,50 +520,8 @@
 		increment_tail(cpu_buf);
 	}
 	release_mm(mm);
-}
- 
- 
-/* Process each CPU's local buffer into the global
- * event buffer.
- */
-static void sync_cpu_buffers(void)
-{
-	int i;
 
-	down(&buffer_sem);
- 
-	for (i = 0; i < NR_CPUS; ++i) {
-		struct oprofile_cpu_buffer * cpu_buf;
- 
-		if (!cpu_possible(i))
-			continue;
- 
-		cpu_buf = &cpu_buffer[i];
- 
-		add_cpu_switch(i);
-		sync_buffer(cpu_buf);
-	}
+	mark_done(cpu);
 
 	up(&buffer_sem);
- 
-	mod_timer(&sync_timer, jiffies + DEFAULT_EXPIRE);
-}
- 
-
-static void wq_sync_buffers(void * data)
-{
-	sync_cpu_buffers();
-}
- 
- 
-/* It is possible that we could have no munmap() or
- * other events for a period of time. This will lead
- * the CPU buffers to overflow and lose samples and
- * context switches. We try to reduce the problem
- * by timing out when nothing happens for a while.
- */
-static void timer_ping(unsigned long data)
-{
-	schedule_work(&sync_wq);
-	/* timer is re-added by the scheduled task */
 }
diff -Nru a/drivers/oprofile/buffer_sync.h b/drivers/oprofile/buffer_sync.h
--- a/drivers/oprofile/buffer_sync.h	2002-10-15 14:45:51 -07:00
+++ b/drivers/oprofile/buffer_sync.h	2004-08-26 23:42:56 -07:00
@@ -16,4 +16,7 @@
 /* remove the hooks */
 void sync_stop(void);
  
+/* sync the given CPU's buffer */
+void sync_buffer(int cpu);
+
 #endif /* OPROFILE_BUFFER_SYNC_H */
diff -Nru a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
--- a/drivers/oprofile/cpu_buffer.c	2004-06-30 12:52:58 -07:00
+++ b/drivers/oprofile/cpu_buffer.c	2004-08-26 23:42:56 -07:00
@@ -9,7 +9,7 @@
  * Each CPU has a local buffer that stores PC value/event
  * pairs. We also log context switches when we notice them.
  * Eventually each CPU's buffer is processed into the global
- * event buffer by sync_cpu_buffers().
+ * event buffer by sync_buffer().
  *
  * We use a local buffer for two reasons: an NMI or similar
  * interrupt cannot synchronise, and high sampling rates
@@ -22,21 +22,24 @@
 #include <linux/errno.h>
  
 #include "cpu_buffer.h"
+#include "buffer_sync.h"
 #include "oprof.h"
 
 struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned;
 
+static void wq_sync_buffer(void *);
+static void timer_ping(unsigned long data);
+#define DEFAULT_TIMER_EXPIRE (HZ / 2)
+int timers_enabled;
+
 static void __free_cpu_buffers(int num)
 {
 	int i;
  
-	for (i=0; i < num; ++i) {
-		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
- 
-		if (!cpu_possible(i)) 
+	for (i = 0; i < NR_CPUS; ++i) {
+		if (!cpu_online(i))
 			continue;
- 
-		vfree(b->buffer);
+		vfree(cpu_buffer[i].buffer);
 	}
 }
  
@@ -47,12 +50,12 @@
  
 	unsigned long buffer_size = fs_cpu_buffer_size;
  
-	for (i=0; i < NR_CPUS; ++i) {
+	for (i = 0; i < NR_CPUS; ++i) {
 		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
  
-		if (!cpu_possible(i)) 
+		if (!cpu_online(i))
 			continue;
- 
+
 		b->buffer = vmalloc(sizeof(struct op_sample) * buffer_size);
 		if (!b->buffer)
 			goto fail;
@@ -64,9 +67,15 @@
 		b->head_pos = 0;
 		b->sample_received = 0;
 		b->sample_lost_overflow = 0;
-		b->sample_lost_task_exit = 0;
+		b->cpu = i;
+		init_timer(&b->timer);
+		b->timer.function = timer_ping;
+		b->timer.data = i;
+		b->timer.expires = jiffies + DEFAULT_TIMER_EXPIRE;
+		INIT_WORK(&b->work, wq_sync_buffer, b);
 	}
 	return 0;
+
 fail:
 	__free_cpu_buffers(i);
 	return -ENOMEM;
@@ -79,6 +88,42 @@
 }
 
 
+void start_cpu_timers(void)
+{
+	int i;
+
+	timers_enabled = 1;
+
+	for (i = 0; i < NR_CPUS; ++i) {
+		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
+
+		if (!cpu_online(i))
+			continue;
+
+		add_timer_on(&b->timer, i);
+	}
+}
+
+
+void end_cpu_timers(void)
+{
+	int i;
+
+	timers_enabled = 0;
+
+	for (i = 0; i < NR_CPUS; ++i) {
+		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
+
+		if (!cpu_online(i))
+			continue;
+
+		del_timer_sync(&b->timer);
+	}
+
+	flush_scheduled_work();
+}
+
+
 /* compute number of available slots in cpu_buffer queue */
 static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b)
 {
@@ -145,21 +190,9 @@
 	/* notice a task switch */
 	if (cpu_buf->last_task != task) {
 		cpu_buf->last_task = task;
-		if (!(task->flags & PF_EXITING)) {
-			cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL;
-			cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task;
-			increment_head(cpu_buf);
-		}
-	}
- 
-	/* If the task is exiting it's not safe to take a sample
-	 * as the task_struct is about to be freed. We can't just
-	 * notify at release_task() time because of CLONE_DETACHED
-	 * tasks that release_task() themselves.
-	 */
-	if (task->flags & PF_EXITING) {
-		cpu_buf->sample_lost_task_exit++;
-		return;
+		cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL;
+		cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task;
+		increment_head(cpu_buf);
 	}
  
 	cpu_buf->buffer[cpu_buf->head_pos].eip = eip;
@@ -177,4 +210,37 @@
 	 */
 	cpu_buf->last_is_kernel = -1;
 	cpu_buf->last_task = NULL;
+}
+
+
+/* FIXME: not guaranteed to be on our CPU */
+static void wq_sync_buffer(void * data)
+{
+	struct oprofile_cpu_buffer * b = (struct oprofile_cpu_buffer *)data;
+	if (b->cpu != smp_processor_id()) {
+		printk("WQ on CPU%d, prefer CPU%d\n",
+		       smp_processor_id(), b->cpu);
+	}
+	sync_buffer(b->cpu);
+
+	/* don't re-add the timer if we're shutting down */
+	if (timers_enabled) {
+		del_timer_sync(&b->timer);
+		add_timer_on(&b->timer, b->cpu);
+	}
+}
+
+
+/* This serves to avoid cpu buffer overflow, and makes sure
+ * the task mortuary progresses
+ */
+static void timer_ping(unsigned long data)
+{
+	struct oprofile_cpu_buffer * b = &cpu_buffer[data];
+	if (b->cpu != smp_processor_id()) {
+		printk("Timer on CPU%d, prefer CPU%d\n",
+		       smp_processor_id(), b->cpu);
+	}
+	schedule_work(&b->work);
+	/* work will re-enable our timer */
 }
diff -Nru a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
--- a/drivers/oprofile/cpu_buffer.h	2003-03-05 13:56:22 -08:00
+++ b/drivers/oprofile/cpu_buffer.h	2004-08-26 23:42:56 -07:00
@@ -12,15 +12,18 @@
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
 #include <linux/cache.h>
  
 struct task_struct;
  
-/* allocate a sample buffer for each CPU */
 int alloc_cpu_buffers(void);
-
 void free_cpu_buffers(void);
 
+void start_cpu_timers(void);
+void end_cpu_timers(void);
+
 /* CPU buffer is composed of such entries (which are
  * also used for context switch notes)
  */
@@ -38,11 +41,13 @@
 	struct op_sample * buffer;
 	unsigned long sample_received;
 	unsigned long sample_lost_overflow;
-	unsigned long sample_lost_task_exit;
+	int cpu;
+	struct timer_list timer;
+	struct work_struct work;
 } ____cacheline_aligned;
 
 extern struct oprofile_cpu_buffer cpu_buffer[];
 
-void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf);
+void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
 
 #endif /* OPROFILE_CPU_BUFFER_H */
diff -Nru a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
--- a/drivers/oprofile/oprofile_stats.c	2004-04-18 09:13:09 -07:00
+++ b/drivers/oprofile/oprofile_stats.c	2004-08-26 23:42:56 -07:00
@@ -29,7 +29,6 @@
 		cpu_buf = &cpu_buffer[i]; 
 		cpu_buf->sample_received = 0;
 		cpu_buf->sample_lost_overflow = 0;
-		cpu_buf->sample_lost_task_exit = 0;
 	}
  
 	atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
@@ -66,8 +65,6 @@
 			&cpu_buf->sample_received);
 		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow",
 			&cpu_buf->sample_lost_overflow);
-		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_task_exit",
-			&cpu_buf->sample_lost_task_exit);
 	}
  
 	oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm",
diff -Nru a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
--- a/drivers/parisc/lasi.c	2003-09-08 15:00:24 -07:00
+++ b/drivers/parisc/lasi.c	2004-08-24 02:09:07 -07:00
@@ -11,7 +11,7 @@
  *      (at your option) any later version.
  *
  *	by Alan Cox <alan@redhat.com> and 
- * 	   Alex deVries <adevries@thepuffingroup.com> 
+ * 	   Alex deVries <alex@onefishtwo.ca>
  */
 
 #include <linux/errno.h>
diff -Nru a/drivers/parisc/superio.c b/drivers/parisc/superio.c
--- a/drivers/parisc/superio.c	2004-08-23 09:53:54 -07:00
+++ b/drivers/parisc/superio.c	2004-08-24 02:09:07 -07:00
@@ -8,7 +8,7 @@
  *	(C) Copyright 2000 Linuxcare, Inc.
  * 	(C) Copyright 2000 Linuxcare Canada, Inc.
  *	(C) Copyright 2000 Martin K. Petersen <mkp@linuxcare.com>
- * 	(C) Copyright 2000 Alex deVries <alex@linuxcare.com>
+ * 	(C) Copyright 2000 Alex deVries <alex@onefishtwo.ca>
  *      (C) Copyright 2001 John Marvin <jsm fc hp com>
  *      (C) Copyright 2003 Grant Grundler <grundler parisc-linux org>
  *
diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
--- a/drivers/parport/parport_pc.c	2004-06-30 09:30:19 -07:00
+++ b/drivers/parport/parport_pc.c	2004-08-27 00:02:35 -07:00
@@ -2636,6 +2636,10 @@
 	netmos_9805,
 	netmos_9815,
 	netmos_9855,
+	netmos_9735,
+	netmos_9835,
+	netmos_9755,
+	netmos_9715
 };
 
 
@@ -2709,6 +2713,10 @@
 	/* netmos_9805 */               { 1, { { 0, -1 }, } }, /* untested */
 	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
 	/* netmos_9855 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
+	/* netmos_9735 */               { 1, { { 2, 3 }, } },  /* untested */
+	/* netmos_9835 */               { 1, { { 2, 3 }, } },  /* untested */
+        /* netmos_9755 */               { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
+        /* netmos_9715 */               { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] = {
@@ -2786,6 +2794,14 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9755,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9755 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9715,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9715 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
diff -Nru a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
--- a/drivers/pci/hotplug/acpiphp_core.c	2004-07-08 16:54:08 -07:00
+++ b/drivers/pci/hotplug/acpiphp_core.c	2004-08-24 02:08:54 -07:00
@@ -61,7 +61,7 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 
 /* export the attention callback registration methods */
 EXPORT_SYMBOL_GPL(acpiphp_register_attention);
diff -Nru a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
--- a/drivers/pci/hotplug/cpcihp_zt5550.c	2004-05-17 09:06:32 -07:00
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c	2004-08-24 02:08:54 -07:00
@@ -298,7 +298,7 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-module_param(poll, bool, 644);
+module_param(poll, bool, 0644);
 MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not");
diff -Nru a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
--- a/drivers/pci/hotplug/cpqphp_core.c	2004-04-25 07:39:40 -07:00
+++ b/drivers/pci/hotplug/cpqphp_core.c	2004-08-24 02:08:54 -07:00
@@ -69,10 +69,10 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-module_param(power_mode, bool, 644);
+module_param(power_mode, bool, 0644);
 MODULE_PARM_DESC(power_mode, "Power mode enabled or not");
 
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 #define CPQHPC_MODULE_MINOR 208
diff -Nru a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
--- a/drivers/pci/hotplug/pci_hotplug_core.c	2004-04-21 09:59:30 -07:00
+++ b/drivers/pci/hotplug/pci_hotplug_core.c	2004-08-24 02:08:54 -07:00
@@ -701,7 +701,7 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 EXPORT_SYMBOL_GPL(pci_hotplug_slots_subsys);
diff -Nru a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
--- a/drivers/pci/hotplug/pciehp_core.c	2004-05-06 02:53:57 -07:00
+++ b/drivers/pci/hotplug/pciehp_core.c	2004-08-24 02:08:54 -07:00
@@ -57,9 +57,9 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-module_param(pciehp_debug, bool, 644);
-module_param(pciehp_poll_mode, bool, 644);
-module_param(pciehp_poll_time, int, 644);
+module_param(pciehp_debug, bool, 0644);
+module_param(pciehp_poll_mode, bool, 0644);
+module_param(pciehp_poll_time, int, 0644);
 MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
diff -Nru a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
--- a/drivers/pci/hotplug/pcihp_skeleton.c	2004-04-23 18:22:46 -07:00
+++ b/drivers/pci/hotplug/pcihp_skeleton.c	2004-08-24 02:08:54 -07:00
@@ -70,7 +70,7 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 static int enable_slot		(struct hotplug_slot *slot);
diff -Nru a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
--- a/drivers/pci/hotplug/shpchp_core.c	2004-05-06 05:19:55 -07:00
+++ b/drivers/pci/hotplug/shpchp_core.c	2004-08-24 02:08:54 -07:00
@@ -57,9 +57,9 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-module_param(shpchp_debug, bool, 644);
-module_param(shpchp_poll_mode, bool, 644);
-module_param(shpchp_poll_time, int, 644);
+module_param(shpchp_debug, bool, 0644);
+module_param(shpchp_poll_mode, bool, 0644);
+module_param(shpchp_poll_time, int, 0644);
 MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
--- a/drivers/pci/pci-driver.c	2004-06-04 06:23:04 -07:00
+++ b/drivers/pci/pci-driver.c	2004-08-21 14:13:40 -07:00
@@ -390,10 +390,9 @@
  * pci_register_driver - register a new pci driver
  * @drv: the driver structure to register
  * 
- * Adds the driver structure to the list of registered drivers
- * Returns the number of pci devices which were claimed by the driver
- * during registration.  The driver remains registered even if the
- * return value is zero.
+ * Adds the driver structure to the list of registered drivers.
+ * Returns a negative value on error. The driver remains registered
+ * even if no device was claimed during registration.
  */
 int
 pci_register_driver(struct pci_driver *drv)
diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids
--- a/drivers/pci/pci.ids	2004-08-02 15:22:50 -07:00
+++ b/drivers/pci/pci.ids	2004-08-24 16:24:39 -07:00
@@ -225,10 +225,22 @@
 		1000 0530  MegaRAID 530 SCSI 320-0X RAID Controller
 		1000 0531  MegaRAID 531 SCSI 320-4X RAID Controller
 		1000 0532  MegaRAID 532 SCSI 320-2X RAID Controller
-		1028 0533  PowerEdge Expandable RAID Controller 4/QC
-		8086 0532  Storage RAID Controller SRCU42X
+		1028 0531  PowerEdge Expandable RAID Controller 4/QC
+		8086 0530  MegaRAID Intel RAID Controller SRCZCRX
+		8086 0532  MegaRAID Intel RAID Controller SRCU42X
 	0408  MegaRAID
-		1028 0002  PowerEdge Expandable RAID Controller 4e/DC
+		1000 0001  MegaRAID SCSI 320-1E RAID Controller
+		1000 0002  MegaRAID SCSI 320-2E RAID Controller
+		1028 0001  Dell PowerEdge RAID Controller PERC4e/SC
+		1028 0002  Dell PowerEdge RAID Controller PERC4e/DC
+		1734 1065  FSC MegaRAID PCI Express ROMB
+		8086 0002  MegaRAID Intel RAID Controller SRCU42E
+	0409  MegaRAID
+		1000 3004  MegaRAID SATA 300-4X RAID Controller
+		1000 3008  MegaRAID SATA 300-8X RAID Controller
+		8086 3008  MegaRAID Intel RAID Controller SRCS28X
+		8086 3431  MegaRAID Intel RAID Controller Alief SROMBU42E
+		8086 3499  MegaRAID Intel RAID Controller Harwich SROMBU42E
 	0621  FC909 Fibre Channel Adapter
 	0622  FC929 Fibre Channel Adapter
 		1000 1020  44929 O Dual Fibre Channel card
@@ -252,7 +264,7 @@
 	1960  MegaRAID
 		1000 0518  MegaRAID 518 SCSI 320-2 Controller
 		1000 0520  MegaRAID 520 SCSI 320-1 Controller
-		1000 0522  MegaRAID 522 i4133 RAID Controller
+		1000 0522  MegaRAID 522 i4 133 RAID Controller
 		1000 0523  MegaRAID SATA 150-6 RAID Controller
 		1000 4523  MegaRAID SATA 150-4 RAID Controller
 		1000 a520  MegaRAID ZCR SCSI 320-0 Controller
@@ -260,6 +272,8 @@
 		1028 0520  MegaRAID 520 DELL PERC 4/SC RAID Controller
 		1028 0531  PowerEdge Expandable RAID Controller 4/QC
 		1028 0533  PowerEdge Expandable RAID Controller 4/QC
+		8086 0520  MegaRAID Intel RAID Controller SRCU41L
+		8086 0523  MegaRAID Intel RAID Controller SRCS16
 1001  Kolter Electronic
 	0010  PCI 1616 Measurement card with 32 digital I/O lines
 	0011  OPTO-PCI Opto-Isolated digital I/O board
@@ -959,6 +973,7 @@
 	0180  Snipe chipset SCSI controller
 		1014 0241  iSeries 2757 DASD IOA
 		1014 0264  Quad Channel PCI-X U320 SCSI RAID Adapter (2780)
+		1014 02BD  Quad Channel PCI-X U320 DDR SCSI RAID Adapter (570F)
 	01a7  PCI-X to PCI-X Bridge
 	01bd  ServeRAID Controller
 		1014 01be  ServeRAID-4M
@@ -981,6 +996,8 @@
 	0266  PCI-X Dual Channel SCSI
 	0268  Gigabit Ethernet-SX Adapter (PCI-X)
 	0269  10/100/1000 Base-TX Ethernet Adapter (PCI-X)
+	028C  Citrine chipset SCSI controller
+		1014 02BE  Dual Channel PCI-X U320 DDR SCSI RAID Adapter (571B)
 	0302  X-Architecture Bridge [Summit]
 	ffff  MPIC-2 interrupt controller
 1015  LSI Logic Corp of Canada
@@ -1244,6 +1261,8 @@
 		1028 016c  PowerEdge Expandable RAID Controller 4e/Si
 		1028 016d  PowerEdge Expandable RAID Controller 4e/Di
 		1028 016e  PowerEdge Expandable RAID Controller 4e/Di
+		1028 016f  PowerEdge Expandable RAID Controller 4e/Di
+		1028 0170  PowerEdge Expandable RAID Controller 4e/Di
 	0014  Remote Access Card 4 Daughter Card SMIC interface
 1029  Siemens Nixdorf IS
 102a  LSI Logic
@@ -2118,6 +2137,8 @@
 		1014 0242  iSeries 2872 DASD IOA
 		1014 0266  Dual Channel PCI-X U320 SCSI Adapter
 		1014 0278  Dual Channel PCI-X U320 SCSI RAID Adapter
+		1014 02D3  Dual Channel PCI-X U320 SCSI Adapter
+		1014 02D4  Dual Channel PCI-X U320 SCSI RAID Adapter
 	ba55  eXtremeRAID 1100 support Device
 	ba56  eXtremeRAID 2000/3000 support Device
 106a  Aten Research Inc
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	2004-08-04 18:20:19 -07:00
+++ b/drivers/pci/probe.c	2004-08-25 06:55:16 -07:00
@@ -571,6 +571,11 @@
 	return PCI_CFG_SPACE_SIZE;
 }
 
+static void pci_release_bus_bridge_dev(struct device *dev)
+{
+	kfree(dev);
+}
+
 /*
  * Read the config data for a PCI device, sanity-check it
  * and fill in the dev structure...
@@ -772,6 +777,7 @@
 
 	memset(dev, 0, sizeof(*dev));
 	dev->parent = parent;
+	dev->release = pci_release_bus_bridge_dev;
 	sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus);
 	device_register(dev);
 	b->bridge = get_device(dev);
diff -Nru a/drivers/pci/remove.c b/drivers/pci/remove.c
--- a/drivers/pci/remove.c	2004-02-03 09:17:30 -08:00
+++ b/drivers/pci/remove.c	2004-08-25 06:55:16 -07:00
@@ -59,6 +59,18 @@
 }
 EXPORT_SYMBOL(pci_remove_device_safe);
 
+void pci_remove_bus(struct pci_bus *b)
+{
+	pci_proc_detach_bus(b);
+
+	spin_lock(&pci_bus_lock);
+	list_del(&b->node);
+	spin_unlock(&pci_bus_lock);
+
+	class_device_unregister(&b->class_dev);
+}
+EXPORT_SYMBOL(pci_remove_bus);
+
 /**
  * pci_remove_bus_device - remove a PCI device and any children
  * @dev: the device to remove
@@ -77,13 +89,7 @@
 		struct pci_bus *b = dev->subordinate;
 
 		pci_remove_behind_bridge(dev);
-		pci_proc_detach_bus(b);
-
-		spin_lock(&pci_bus_lock);
-		list_del(&b->node);
-		spin_unlock(&pci_bus_lock);
-
-		class_device_unregister(&b->class_dev);
+		pci_remove_bus(b);
 		dev->subordinate = NULL;
 	}
 
diff -Nru a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
--- a/drivers/pcmcia/au1000_generic.c	2004-03-14 12:10:39 -08:00
+++ b/drivers/pcmcia/au1000_generic.c	2004-08-22 07:10:23 -07:00
@@ -566,7 +566,6 @@
 au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
 {
 	unsigned int speed;
-	unsigned long start;
 	u_long flags;
 
 	if(map->map>=MAX_WIN){
@@ -588,25 +587,19 @@
 	}
 
 	spin_lock_irqsave(&pcmcia_lock, flags);
-	start=map->sys_start;
-
-	if(map->sys_stop==0)
-		map->sys_stop=MAP_SIZE-1;
-
 	if (map->flags & MAP_ATTRIB) {
-		map->sys_start = pcmcia_socket[sock].phys_attr + 
+		map->static_start = pcmcia_socket[sock].phys_attr + 
 			map->card_start;
 	}
 	else {
-		map->sys_start = pcmcia_socket[sock].phys_mem + 
+		map->static_start = pcmcia_socket[sock].phys_mem + 
 			map->card_start;
 	}
 
-	map->sys_stop=map->sys_start+(map->sys_stop-start);
 	pcmcia_socket[sock].mem_map[map->map]=*map;
 	spin_unlock_irqrestore(&pcmcia_lock, flags);
-	debug(3, "set_mem_map %d start %x stop %x card_start %x\n", 
-			map->map, map->sys_start, map->sys_stop, 
+	debug(3, "set_mem_map %d start %x card_start %x\n", 
+			map->map, map->static_start,
 			map->card_start);
 	return 0;
 
diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
--- a/drivers/pcmcia/cistpl.c	2004-06-20 13:51:18 -07:00
+++ b/drivers/pcmcia/cistpl.c	2004-08-22 07:39:14 -07:00
@@ -114,8 +114,6 @@
 	    printk(KERN_NOTICE "cs: unable to map card memory!\n");
 	    return NULL;
 	}
-	mem->sys_start = mem->res->start;
-	mem->sys_stop = mem->res->end;
 	s->cis_virt = ioremap(mem->res->start, s->map_size);
     }
     mem->card_start = card_offset;
@@ -124,7 +122,7 @@
     if (s->features & SS_CAP_STATIC_MAP) {
 	if (s->cis_virt)
 	    iounmap(s->cis_virt);
-	s->cis_virt = ioremap(mem->sys_start, s->map_size);
+	s->cis_virt = ioremap(mem->static_start, s->map_size);
     }
     return s->cis_virt;
 }
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c	2004-07-10 16:25:06 -07:00
+++ b/drivers/pcmcia/cs.c	2004-08-22 07:39:14 -07:00
@@ -1886,11 +1886,6 @@
 				       (*handle)->dev_info, s);
 	if (!win->ctl.res)
 	    return CS_IN_USE;
-	win->ctl.sys_start = win->ctl.res->start;
-	win->ctl.sys_stop = win->ctl.res->end;
-    } else {
-	win->ctl.sys_start = req->Base;
-	win->ctl.sys_stop = req->Base + req->Size - 1;
     }
     (*handle)->state |= CLIENT_WIN_REQ(w);
 
@@ -1912,7 +1907,11 @@
     s->state |= SOCKET_WIN_REQ(w);
 
     /* Return window handle */
-    req->Base = win->ctl.sys_start;
+    if (s->features & SS_CAP_STATIC_MAP) {
+	req->Base = win->ctl.static_start;
+    } else {
+	req->Base = win->ctl.res->start;
+    }
     *wh = win;
     
     return CS_SUCCESS;
diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
--- a/drivers/pcmcia/hd64465_ss.c	2003-09-27 16:04:08 -07:00
+++ b/drivers/pcmcia/hd64465_ss.c	2004-08-22 07:10:24 -07:00
@@ -636,19 +636,17 @@
     	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 	struct pccard_mem_map *smem;
 	int map = mem->map;
-	unsigned long paddr, size;
+	unsigned long paddr;
 
 #if 0
-    	DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, sys_start=0x%08lx, sys_end=0x%08lx, card_start=0x%08x)\n",
-	    sock, map, mem->flags, mem->sys_start, mem->sys_stop, mem->card_start);
+    	DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, card_start=0x%08x)\n",
+	    sock, map, mem->flags, mem->card_start);
 #endif
 
 	if (map >= MAX_WIN)
 	    return -EINVAL;
 	smem = &sp->mem_maps[map];
 	
-	size = mem->sys_stop - mem->sys_start + 1;
-	
 	paddr = sp->mem_base;	    	    /* base of Attribute mapping */
 	if (!(mem->flags & MAP_ATTRIB))
 	    paddr += HD64465_PCC_WINDOW;    /* base of Common mapping */
@@ -660,8 +658,7 @@
 	 * queries our fixed mapping.  I wish this fact had been
 	 * documented - Greg Banks.
 	 */
-    	mem->sys_start = paddr;
-	mem->sys_stop = paddr + size - 1;
+    	mem->static_start = paddr;
 	
 	*smem = *mem;
 	
diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
--- a/drivers/pcmcia/i82092.c	2004-06-20 13:51:18 -07:00
+++ b/drivers/pcmcia/i82092.c	2004-08-22 07:39:14 -07:00
@@ -422,7 +422,7 @@
 	int i;
 	struct resource res = { .start = 0, .end = 0x0fff };
         pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, };
+	pccard_mem_map mem = { .res = &res, };
         
         enter("i82092aa_init");
                         
@@ -706,11 +706,15 @@
 
 static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem)
 {
-	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
+	struct socket_info *sock_info = container_of(socket, struct socket_info, socket);
+	unsigned int sock = sock_info->number;
+	struct pci_bus_region region;
 	unsigned short base, i;
 	unsigned char map;
 	
 	enter("i82092aa_set_mem_map");
+
+	pcibios_resource_to_bus(sock_info->dev, &region, mem->res);
 	
 	map = mem->map;
 	if (map > 4) {
@@ -719,10 +723,10 @@
 	}
 	
 	
-	if ( (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) ||
+	if ( (mem->card_start > 0x3ffffff) || (region.start > region.end) ||
 	     (mem->speed > 1000) ) {
 		leave("i82092aa_set_mem_map: invalid address / speed");
-		printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,mem->sys_start, mem->sys_stop, mem->card_start);
+		printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,region.start, region.end, mem->card_start);
 		return -EINVAL;
 	}
 	
@@ -731,11 +735,11 @@
 	              indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
 	                 
 	                 
-/* 	printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, mem->sys_start,mem->sys_stop,sock,mem->speed,mem->flags & MAP_ACTIVE);  */
+/* 	printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, region.start,region.end,sock,mem->speed,mem->flags & MAP_ACTIVE);  */
 
 	/* write the start address */
 	base = I365_MEM(map);
-	i = (mem->sys_start >> 12) & 0x0fff;
+	i = (region.start >> 12) & 0x0fff;
 	if (mem->flags & MAP_16BIT) 
 		i |= I365_MEM_16BIT;
 	if (mem->flags & MAP_0WS)
@@ -744,7 +748,7 @@
 		               
 	/* write the stop address */
 	
-	i= (mem->sys_stop >> 12) & 0x0fff;
+	i= (region.end >> 12) & 0x0fff;
 	switch (to_cycles(mem->speed)) {
 		case 0:
 			break;
@@ -763,7 +767,7 @@
 	
 	/* card start */
 	
-	i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+	i = ((mem->card_start - region.start) >> 12) & 0x3fff;
 	if (mem->flags & MAP_WRPROT)
 		i |= I365_MEM_WRPROT;
 	if (mem->flags & MAP_ATTRIB) {
diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c	2004-06-26 08:52:02 -07:00
+++ b/drivers/pcmcia/i82365.c	2004-08-22 07:39:15 -07:00
@@ -1159,13 +1159,13 @@
     
     debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
 	  "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
-	  mem->sys_start, mem->sys_stop, mem->card_start);
+	  mem->res->start, mem->res->end, mem->card_start);
 
     map = mem->map;
     if ((map > 4) || (mem->card_start > 0x3ffffff) ||
-	(mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
+	(mem->res->start > mem->res->end) || (mem->speed > 1000))
 	return -EINVAL;
-    if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))
+    if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff))
 	return -EINVAL;
 	
     /* Turn off the window before changing anything */
@@ -1173,12 +1173,12 @@
 	i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
     
     base = I365_MEM(map);
-    i = (mem->sys_start >> 12) & 0x0fff;
+    i = (mem->res->start >> 12) & 0x0fff;
     if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
     if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
     i365_set_pair(sock, base+I365_W_START, i);
     
-    i = (mem->sys_stop >> 12) & 0x0fff;
+    i = (mem->res->end >> 12) & 0x0fff;
     switch (to_cycles(mem->speed)) {
     case 0:	break;
     case 1:	i |= I365_MEM_WS0; break;
@@ -1187,7 +1187,7 @@
     }
     i365_set_pair(sock, base+I365_W_STOP, i);
     
-    i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+    i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
     if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
     if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
     i365_set_pair(sock, base+I365_W_OFF, i);
@@ -1309,7 +1309,7 @@
 	int i;
 	struct resource res = { .start = 0, .end = 0x1000 };
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, };
+	pccard_mem_map mem = { .res = &res, };
 
 	for (i = 0; i < 2; i++) {
 		io.map = i;
diff -Nru a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
--- a/drivers/pcmcia/pd6729.c	2004-08-12 08:26:53 -07:00
+++ b/drivers/pcmcia/pd6729.c	2004-08-22 07:39:15 -07:00
@@ -502,10 +502,10 @@
 		return -EINVAL;
 	}
 
-	if ((mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) {
+	if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) {
 		printk("pd6729_set_mem_map: invalid address / speed");
 		/* printk("invalid mem map for socket %i : %lx to %lx with a start of %x\n",
-			 sock, mem->sys_start, mem->sys_stop, mem->card_start); */
+			 sock, mem->res->start, mem->res->end, mem->card_start); */
 		return -EINVAL;
 	}
 
@@ -515,7 +515,7 @@
 
 	/* write the start address */
 	base = I365_MEM(map);
-	i = (mem->sys_start >> 12) & 0x0fff;
+	i = (mem->res->start >> 12) & 0x0fff;
 	if (mem->flags & MAP_16BIT)
 		i |= I365_MEM_16BIT;
 	if (mem->flags & MAP_0WS)
@@ -524,7 +524,7 @@
 
 	/* write the stop address */
 
-	i= (mem->sys_stop >> 12) & 0x0fff;
+	i= (mem->res->end >> 12) & 0x0fff;
 	switch (to_cycles(mem->speed)) {
 	case 0:
 		break;
@@ -543,11 +543,11 @@
 
 	/* Take care of high byte */
 	indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
-	indirect_write(socket, PD67_EXT_DATA, mem->sys_start >> 24);
+	indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24);
 
 	/* card start */
 
-	i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+	i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
 	if (mem->flags & MAP_WRPROT)
 		i |= I365_MEM_WRPROT;
 	if (mem->flags & MAP_ATTRIB) {
@@ -577,7 +577,7 @@
 	int i;
 	struct resource res = { .end = 0x0fff };
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff };
+	pccard_mem_map mem = { .res = &res, };
 
 	pd6729_set_socket(sock, &dead_socket);
 	for (i = 0; i < 2; i++) {
diff -Nru a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
--- a/drivers/pcmcia/rsrc_mgr.c	2004-06-26 01:25:50 -07:00
+++ b/drivers/pcmcia/rsrc_mgr.c	2004-08-22 07:39:15 -07:00
@@ -301,8 +301,6 @@
 {
 	int ret = -1;
 
-	s->cis_mem.sys_start = res->start;
-	s->cis_mem.sys_stop = res->end;
 	s->cis_mem.res = res;
 	s->cis_virt = ioremap(res->start, s->map_size);
 	if (s->cis_virt) {
@@ -312,8 +310,6 @@
 		s->cis_virt = NULL;
 		destroy_cis_cache(s);
 	}
-	s->cis_mem.sys_start = 0;
-	s->cis_mem.sys_stop = 0;
 	s->cis_mem.res = NULL;
 	if ((ret != 0) || (info->Chains == 0))
 		return 0;
@@ -332,8 +328,6 @@
 		map.map = 0;
 		map.flags = MAP_ACTIVE;
 		map.speed = 0;
-		map.sys_start = res->start;
-		map.sys_stop = res->end;
 		map.res = res;
 		map.card_start = 0;
 		s->ops->set_mem_map(s, &map);
diff -Nru a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
--- a/drivers/pcmcia/soc_common.c	2004-06-02 07:54:27 -07:00
+++ b/drivers/pcmcia/soc_common.c	2004-08-22 07:10:24 -07:00
@@ -448,9 +448,7 @@
 
 	skt->ops->set_timing(skt);
 
-	map->sys_stop -= map->sys_start;
-	map->sys_stop += res->start + map->card_start;
-	map->sys_start = res->start + map->card_start;
+	map->static_start = res->start + map->card_start;
 
 	return 0;
 }
@@ -662,6 +660,7 @@
 int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
 {
 	struct skt_dev_info *sinfo;
+	struct soc_pcmcia_socket *skt;
 	int ret, i;
 
 	down(&soc_pcmcia_sockets_lock);
@@ -679,7 +678,7 @@
 	 * Initialise the per-socket structure.
 	 */
 	for (i = 0; i < nr; i++) {
-		struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+		skt = &sinfo->skt[i];
 
 		skt->socket.ops = &soc_common_pcmcia_operations;
 		skt->socket.owner = ops->owner;
@@ -777,7 +776,7 @@
 	goto out;
 
 	do {
-		struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+		skt = &sinfo->skt[i];
 
 		del_timer_sync(&skt->poll_timer);
 		pcmcia_unregister_socket(&skt->socket);
diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
--- a/drivers/pcmcia/tcic.c	2004-06-20 13:51:19 -07:00
+++ b/drivers/pcmcia/tcic.c	2004-08-22 07:39:15 -07:00
@@ -829,15 +829,15 @@
 
     debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, "
 	  "%#5.5lx-%#5.5lx, %#5.5x)\n", psock, mem->map, mem->flags,
-	  mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
+	  mem->speed, mem->res->start, mem->res->end, mem->card_start);
     if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
-	(mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff) ||
-	(mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
+	(mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) ||
+	(mem->res->start > mem->res->end) || (mem->speed > 1000))
 	return -EINVAL;
     tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
     addr = TCIC_MWIN(psock, mem->map);
 
-    base = mem->sys_start; len = mem->sys_stop - mem->sys_start;
+    base = mem->res->start; len = mem->res->end - mem->res->start;
     if ((len & (len+1)) || (base & len)) return -EINVAL;
     if (len == 0x0fff)
 	base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
@@ -846,7 +846,7 @@
     tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
     tcic_setw(TCIC_DATA, base);
     
-    mmap = mem->card_start - mem->sys_start;
+    mmap = mem->card_start - mem->res->start;
     mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
     if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
     tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
@@ -870,7 +870,7 @@
 	int i;
 	struct resource res = { .start = 0, .end = 0x1000 };
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, };
+	pccard_mem_map mem = { .res = &res, };
 
 	for (i = 0; i < 2; i++) {
 		io.map = i;
diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
--- a/drivers/pcmcia/yenta_socket.c	2004-06-26 08:52:02 -07:00
+++ b/drivers/pcmcia/yenta_socket.c	2004-08-22 07:39:15 -07:00
@@ -343,14 +343,17 @@
 static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 {
 	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	struct pci_bus_region region;
 	int map;
 	unsigned char addr, enable;
 	unsigned int start, stop, card_start;
 	unsigned short word;
 
+	pcibios_resource_to_bus(socket->dev, &region, mem->res);
+
 	map = mem->map;
-	start = mem->sys_start;
-	stop = mem->sys_stop;
+	start = region.start;
+	stop = region.end;
 	card_start = mem->card_start;
 
 	if (map > 4 || start > stop || ((start ^ stop) >> 24) ||
@@ -447,7 +450,7 @@
 	int i;
 	struct resource res = { .start = 0, .end = 0x0fff };
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, };
+	pccard_mem_map mem = { .res = &res, };
 
 	yenta_set_socket(&socket->socket, &dead_socket);
 	for (i = 0; i < 2; i++) {
diff -Nru a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
--- a/drivers/s390/char/sclp.c	2004-07-06 19:32:22 -07:00
+++ b/drivers/s390/char/sclp.c	2004-08-27 00:02:36 -07:00
@@ -20,6 +20,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/cpumask.h>
+#include <linux/reboot.h>
 #include <asm/s390_ext.h>
 #include <asm/processor.h>
 
@@ -60,6 +61,7 @@
 #define SCLP_INIT		0
 #define SCLP_RUNNING		1
 #define SCLP_READING		2
+#define SCLP_SHUTDOWN		3
 
 #define SCLP_INIT_POLL_INTERVAL	1
 #define SCLP_BUSY_POLL_INTERVAL	1
@@ -606,10 +608,12 @@
 	sccb->mask_length = sizeof(sccb_mask_t);
 	/* copy in the sccb mask of the registered event types */
 	spin_lock_irqsave(&sclp_lock, flags);
-	list_for_each(l, &sclp_reg_list) {
-		t = list_entry(l, struct sclp_register, list);
-		sccb->receive_mask |= t->receive_mask;
-		sccb->send_mask |= t->send_mask;
+	if (!test_bit(SCLP_SHUTDOWN, &sclp_status)) {
+		list_for_each(l, &sclp_reg_list) {
+			t = list_entry(l, struct sclp_register, list);
+			sccb->receive_mask |= t->receive_mask;
+			sccb->send_mask |= t->send_mask;
+		}
 	}
 	sccb->sclp_receive_mask = 0;
 	sccb->sclp_send_mask = 0;
@@ -647,9 +651,10 @@
 		/* WRITEMASK failed - we cannot rely on receiving a state
 		   change event, so initially, polling is the only alternative
 		   for us to ever become operational. */
-		if (!timer_pending(&retry_timer) ||
-		    !mod_timer(&retry_timer,
-			       jiffies + SCLP_INIT_POLL_INTERVAL*HZ)) {
+		if (!test_bit(SCLP_SHUTDOWN, &sclp_status) &&
+		    (!timer_pending(&retry_timer) ||
+		     !mod_timer(&retry_timer,
+			       jiffies + SCLP_INIT_POLL_INTERVAL*HZ))) {
 			retry_timer.function = sclp_init_mask_retry;
 			retry_timer.data = 0;
 			retry_timer.expires = jiffies +
@@ -671,6 +676,26 @@
 	sclp_init_mask();
 }
 
+/* Reboot event handler - reset send and receive mask to prevent pending SCLP
+ * events from interfering with rebooted system. */
+static int
+sclp_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	unsigned long flags;
+
+	/* Note: need spinlock to maintain atomicity when accessing global
+         * variables. */
+	spin_lock_irqsave(&sclp_lock, flags);
+	set_bit(SCLP_SHUTDOWN, &sclp_status);
+	spin_unlock_irqrestore(&sclp_lock, flags);
+	sclp_init_mask();
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block sclp_reboot_notifier = {
+	.notifier_call = sclp_reboot_event
+};
+
 /*
  * sclp setup function. Called early (no kmalloc!) from sclp_console_init().
  */
@@ -690,6 +715,10 @@
 	INIT_LIST_HEAD(&sclp_reg_list);
 	list_add(&sclp_state_change_event.list, &sclp_reg_list);
 	list_add(&sclp_quiesce_event.list, &sclp_reg_list);
+
+	rc = register_reboot_notifier(&sclp_reboot_notifier);
+	if (rc)
+		return rc;
 
 	/*
 	 * request the 0x2401 external interrupt
diff -Nru a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
--- a/drivers/s390/cio/qdio.c	2004-08-07 11:05:36 -07:00
+++ b/drivers/s390/cio/qdio.c	2004-08-27 00:02:35 -07:00
@@ -56,7 +56,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.84 $"
+#define VERSION_QDIO_C "$Revision: 1.86 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -365,7 +365,7 @@
 	 * small window we can miss between resetting it and
 	 * checking for PRIMED state 
 	 */
-	if (q->is_iqdio_q)
+	if (q->is_thinint_q)
 		tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
 	return 0;
 
diff -Nru a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
--- a/drivers/s390/net/lcs.c	2004-08-15 19:53:29 -07:00
+++ b/drivers/s390/net/lcs.c	2004-08-27 00:02:35 -07:00
@@ -11,7 +11,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
- *    $Revision: 1.85 $	 $Date: 2004/08/04 11:05:43 $
+ *    $Revision: 1.89 $	 $Date: 2004/08/24 10:49:27 $
  *
  * 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
@@ -59,7 +59,7 @@
 /**
  * initialization string for output
  */
-#define VERSION_LCS_C  "$Revision: 1.85 $"
+#define VERSION_LCS_C  "$Revision: 1.89 $"
 
 static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
 static char debug_buffer[255];
@@ -70,6 +70,7 @@
 static void lcs_tasklet(unsigned long);
 static void lcs_start_kernel_thread(struct lcs_card *card);
 static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *);
+static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *);
 
 /**
  * Debug Facility Stuff
@@ -100,9 +101,9 @@
 		return -ENOMEM;
 	}
 	debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view);
-	debug_set_level(lcs_dbf_setup, 2);
+	debug_set_level(lcs_dbf_setup, 4);
 	debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view);
-	debug_set_level(lcs_dbf_trace, 2);
+	debug_set_level(lcs_dbf_trace, 4);
 	return 0;
 }
 
@@ -316,7 +317,106 @@
 	init_waitqueue_head(&card->write.wait_q);
 }
 
+static void
+lcs_set_allowed_threads(struct lcs_card *card, unsigned long threads)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+	card->thread_allowed_mask = threads;
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+	wake_up(&card->wait_q);
+}
+static inline int
+lcs_threads_running(struct lcs_card *card, unsigned long threads)
+{
+        unsigned long flags;
+        int rc = 0;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+        rc = (card->thread_running_mask & threads);
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        return rc;
+}
+
+static int
+lcs_wait_for_threads(struct lcs_card *card, unsigned long threads)
+{
+        return wait_event_interruptible(card->wait_q,
+                        lcs_threads_running(card, threads) == 0);
+}
+
+static inline int
+lcs_set_thread_start_bit(struct lcs_card *card, unsigned long thread)
+{
+        unsigned long flags;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+        if ( !(card->thread_allowed_mask & thread) ||
+              (card->thread_start_mask & thread) ) {
+                spin_unlock_irqrestore(&card->mask_lock, flags);
+                return -EPERM;
+        }
+        card->thread_start_mask |= thread;
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        return 0;
+}
+
+static void
+lcs_clear_thread_running_bit(struct lcs_card *card, unsigned long thread)
+{
+        unsigned long flags;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+        card->thread_running_mask &= ~thread;
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        wake_up(&card->wait_q);
+}
+
+static inline int
+__lcs_do_run_thread(struct lcs_card *card, unsigned long thread)
+{
+        unsigned long flags;
+        int rc = 0;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+        if (card->thread_start_mask & thread){
+                if ((card->thread_allowed_mask & thread) &&
+                    !(card->thread_running_mask & thread)){
+                        rc = 1;
+                        card->thread_start_mask &= ~thread;
+                        card->thread_running_mask |= thread;
+                } else
+                        rc = -EPERM;
+        }
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        return rc;
+}
+
+static int
+lcs_do_run_thread(struct lcs_card *card, unsigned long thread)
+{
+        int rc = 0;
+        wait_event(card->wait_q,
+                   (rc = __lcs_do_run_thread(card, thread)) >= 0);
+        return rc;
+}
+
+static int
+lcs_do_start_thread(struct lcs_card *card, unsigned long thread)
+{
+        unsigned long flags;
+        int rc = 0;
 
+	spin_lock_irqsave(&card->mask_lock, flags);
+        LCS_DBF_TEXT_(4, trace, "  %02x%02x%02x",
+                        (u8) card->thread_start_mask,
+                        (u8) card->thread_allowed_mask,
+                        (u8) card->thread_running_mask);
+        rc = (card->thread_start_mask & thread);
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        return rc;
+}
 
 /**
  * Initialize channels,card and state machines.
@@ -337,34 +437,49 @@
 	/* Initialize kernel thread task used for LGW commands. */
 	INIT_WORK(&card->kernel_thread_starter,
 		  (void *)lcs_start_kernel_thread,card);
-	card->thread_mask = 0;
+	card->thread_start_mask = 0;
+	card->thread_allowed_mask = 0;
+	card->thread_running_mask = 0;
+	init_waitqueue_head(&card->wait_q);
 	spin_lock_init(&card->lock);
 	spin_lock_init(&card->ipm_lock);
+	spin_lock_init(&card->mask_lock);
 #ifdef CONFIG_IP_MULTICAST
 	INIT_LIST_HEAD(&card->ipm_list);
 #endif
 	INIT_LIST_HEAD(&card->lancmd_waiters);
 }
 
+static inline void
+lcs_clear_multicast_list(struct lcs_card *card)
+{
+#ifdef	CONFIG_IP_MULTICAST
+	struct list_head *l, *n;
+	struct lcs_ipm_list *ipm;
+	unsigned long flags;
+	/* Free multicast list. */
+	LCS_DBF_TEXT(3, setup, "clmclist");
+	spin_lock_irqsave(&card->ipm_lock, flags);
+	list_for_each_safe(l, n, &card->ipm_list) {
+		ipm = list_entry(l, struct lcs_ipm_list, list);
+		list_del(&ipm->list);
+		if (ipm->ipm_state != LCS_IPM_STATE_SET_REQUIRED)
+			lcs_send_delipm(card, ipm);
+		kfree(ipm);
+	}
+	spin_unlock_irqrestore(&card->ipm_lock, flags);
+#endif
+}
 /**
  * Cleanup channels,card and state machines.
  */
 static void
 lcs_cleanup_card(struct lcs_card *card)
 {
-	struct list_head *l, *n;
-	struct lcs_ipm_list *ipm_list;
 
 	LCS_DBF_TEXT(3, setup, "cleancrd");
 	LCS_DBF_HEX(2,setup,&card,sizeof(void*));
-#ifdef	CONFIG_IP_MULTICAST
-	/* Free multicast list. */
-	list_for_each_safe(l, n, &card->ipm_list) {
-		ipm_list = list_entry(l, struct lcs_ipm_list, list);
-		list_del(&ipm_list->list);
-		kfree(ipm_list);
-	}
-#endif
+
 	if (card->dev != NULL)
 		free_netdev(card->dev);
 	/* Cleanup channels. */
@@ -651,6 +766,44 @@
 	return buffer;
 }
 
+
+static void
+lcs_get_reply(struct lcs_reply *reply)
+{
+	WARN_ON(atomic_read(&reply->refcnt) <= 0);
+	atomic_inc(&reply->refcnt);
+}
+
+static void
+lcs_put_reply(struct lcs_reply *reply)
+{
+        WARN_ON(atomic_read(&reply->refcnt) <= 0);
+        if (atomic_dec_and_test(&reply->refcnt)) {
+		kfree(reply);
+	}
+
+}
+
+static struct lcs_reply *
+lcs_alloc_reply(struct lcs_cmd *cmd)
+{
+	struct lcs_reply *reply;
+
+	LCS_DBF_TEXT(4, trace, "getreply");
+
+	reply = kmalloc(sizeof(struct lcs_reply), GFP_ATOMIC);
+	if (!reply)
+		return NULL;
+	memset(reply,0,sizeof(struct lcs_reply));
+	atomic_set(&reply->refcnt,1);
+	reply->sequence_no = cmd->sequence_no;
+	reply->received = 0;
+	reply->rc = 0;
+	init_waitqueue_head(&reply->wait_q);
+
+	return reply;
+}
+
 /**
  * Notifier function for lancmd replies. Called from read irq.
  */
@@ -665,12 +818,14 @@
 	list_for_each_safe(l, n, &card->lancmd_waiters) {
 		reply = list_entry(l, struct lcs_reply, list);
 		if (reply->sequence_no == cmd->sequence_no) {
-			list_del(&reply->list);
+			lcs_get_reply(reply);
+			list_del_init(&reply->list);
 			if (reply->callback != NULL)
 				reply->callback(card, cmd);
 			reply->received = 1;
 			reply->rc = cmd->return_code;
 			wake_up(&reply->wait_q);
+			lcs_put_reply(reply);
 			break;
 		}
 	}
@@ -683,50 +838,66 @@
 void
 lcs_lancmd_timeout(unsigned long data)
 {
-	struct lcs_reply *reply;
+	struct lcs_reply *reply, *list_reply, *r;
+	unsigned long flags;
 
 	LCS_DBF_TEXT(4, trace, "timeout");
 	reply = (struct lcs_reply *) data;
-	list_del(&reply->list);
-	reply->received = 1;
-	reply->rc = -ETIME;
-	wake_up(&reply->wait_q);
+	spin_lock_irqsave(&reply->card->lock, flags);
+	list_for_each_entry_safe(list_reply, r,
+				 &reply->card->lancmd_waiters,list) {
+		if (reply == list_reply) {
+			lcs_get_reply(reply);
+			list_del_init(&reply->list);
+			spin_unlock_irqrestore(&reply->card->lock, flags);
+			reply->received = 1;
+			reply->rc = -ETIME;
+			wake_up(&reply->wait_q);
+			lcs_put_reply(reply);
+			return;
+		}
+	}
+	spin_unlock_irqrestore(&reply->card->lock, flags);
 }
 
 static int
 lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
 		void (*reply_callback)(struct lcs_card *, struct lcs_cmd *))
 {
-	struct lcs_reply reply;
+	struct lcs_reply *reply;
 	struct lcs_cmd *cmd;
 	struct timer_list timer;
+	unsigned long flags;
 	int rc;
 
 	LCS_DBF_TEXT(4, trace, "sendcmd");
 	cmd = (struct lcs_cmd *) buffer->data;
-	cmd->sequence_no = ++card->sequence_no;
 	cmd->return_code = 0;
-	reply.sequence_no = cmd->sequence_no;
-	reply.callback = reply_callback;
-	reply.received = 0;
-	reply.rc = 0;
-	init_waitqueue_head(&reply.wait_q);
-	spin_lock(&card->lock);
-	list_add_tail(&reply.list, &card->lancmd_waiters);
-	spin_unlock(&card->lock);
+	cmd->sequence_no = card->sequence_no++;
+	reply = lcs_alloc_reply(cmd);
+	if (!reply)
+		return -ENOMEM;
+	reply->callback = reply_callback;
+	reply->card = card;
+	spin_lock_irqsave(&card->lock, flags);
+	list_add_tail(&reply->list, &card->lancmd_waiters);
+	spin_unlock_irqrestore(&card->lock, flags);
+
 	buffer->callback = lcs_release_buffer;
 	rc = lcs_ready_buffer(&card->write, buffer);
 	if (rc)
 		return rc;
 	init_timer(&timer);
 	timer.function = lcs_lancmd_timeout;
-	timer.data = (unsigned long) &reply;
+	timer.data = (unsigned long) reply;
 	timer.expires = jiffies + HZ*card->lancmd_timeout;
 	add_timer(&timer);
-	wait_event(reply.wait_q, reply.received);
-	del_timer(&timer);
-	LCS_DBF_TEXT_(4, trace, "rc:%d",reply.rc);
-	return reply.rc ? -EIO : 0;
+	wait_event(reply->wait_q, reply->received);
+	del_timer_sync(&timer);
+	LCS_DBF_TEXT_(4, trace, "rc:%d",reply->rc);
+	rc = reply->rc;
+	lcs_put_reply(reply);
+	return rc ? -EIO : 0;
 }
 
 /**
@@ -942,9 +1113,10 @@
 {
 	struct list_head *l, *n;
 	struct lcs_ipm_list *ipm;
+	unsigned long flags;
 
 	LCS_DBF_TEXT(4,trace, "fixipm");
-	spin_lock(&card->ipm_lock);
+	spin_lock_irqsave(&card->ipm_lock, flags);
 	list_for_each_safe(l, n, &card->ipm_list) {
 		ipm = list_entry(l, struct lcs_ipm_list, list);
 		switch (ipm->ipm_state) {
@@ -964,9 +1136,9 @@
 			break;
 		}
 	}
+	spin_unlock_irqrestore(&card->ipm_lock, flags);
 	if (card->state == DEV_STATE_UP)
 		netif_wake_queue(card->dev);
-	spin_unlock(&card->ipm_lock);
 }
 
 /**
@@ -985,51 +1157,67 @@
 /**
  * function called by net device to handle multicast address relevant things
  */
-static int
-lcs_register_mc_addresses(void *data)
+static inline void
+lcs_remove_mc_addresses(struct lcs_card *card, struct in_device *in4_dev)
 {
-	struct lcs_card *card;
-	char buf[MAX_ADDR_LEN];
-	struct list_head *l;
 	struct ip_mc_list *im4;
-	struct in_device *in4_dev;
-	struct lcs_ipm_list *ipm, *tmp;
-
-	daemonize("regipm");
-	LCS_DBF_TEXT(4, trace, "regmulti");
+	struct list_head *l;
+	struct lcs_ipm_list *ipm;
+	unsigned long flags;
+	char buf[MAX_ADDR_LEN];
 
-	card = (struct lcs_card *) data;
-	in4_dev = in_dev_get(card->dev);
-	if (in4_dev == NULL)
-		return 0;
-	read_lock(&in4_dev->mc_list_lock);
-	spin_lock(&card->ipm_lock);
-	/* Check for multicast addresses to be removed. */
+	LCS_DBF_TEXT(4, trace, "remmclst");
+	spin_lock_irqsave(&card->ipm_lock, flags);
 	list_for_each(l, &card->ipm_list) {
 		ipm = list_entry(l, struct lcs_ipm_list, list);
 		for (im4 = in4_dev->mc_list; im4 != NULL; im4 = im4->next) {
 			lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev);
-			if (memcmp(buf, &ipm->ipm.mac_addr,
-				   LCS_MAC_LENGTH) == 0 &&
-			    ipm->ipm.ip_addr == im4->multiaddr)
+			if ( (ipm->ipm.ip_addr == im4->multiaddr) &&
+			     (memcmp(buf, &ipm->ipm.mac_addr,
+				     LCS_MAC_LENGTH) == 0) )
 				break;
 		}
 		if (im4 == NULL)
 			ipm->ipm_state = LCS_IPM_STATE_DEL_REQUIRED;
 	}
-	/* Check for multicast addresses to be added. */
+	spin_unlock_irqrestore(&card->ipm_lock, flags);
+}
+
+static inline struct lcs_ipm_list *
+lcs_check_addr_entry(struct lcs_card *card, struct ip_mc_list *im4, char *buf)
+{
+	struct lcs_ipm_list *tmp, *ipm = NULL;
+	struct list_head *l;
+	unsigned long flags;
+
+	LCS_DBF_TEXT(4, trace, "chkmcent");
+	spin_lock_irqsave(&card->ipm_lock, flags);
+	list_for_each(l, &card->ipm_list) {
+		tmp = list_entry(l, struct lcs_ipm_list, list);
+		if ( (tmp->ipm.ip_addr == im4->multiaddr) &&
+		     (memcmp(buf, &tmp->ipm.mac_addr,
+			     LCS_MAC_LENGTH) == 0) ) {
+			ipm = tmp;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&card->ipm_lock, flags);
+	return ipm;
+}
+
+static inline void
+lcs_set_mc_addresses(struct lcs_card *card, struct in_device *in4_dev)
+{
+
+	struct ip_mc_list *im4;
+	struct lcs_ipm_list *ipm;
+	char buf[MAX_ADDR_LEN];
+	unsigned long flags;
+
+	LCS_DBF_TEXT(4, trace, "setmclst");
 	for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
 		lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev);
-		ipm = NULL;
-		list_for_each(l, &card->ipm_list) {
-			tmp = list_entry(l, struct lcs_ipm_list, list);
-			if (memcmp(buf, &tmp->ipm.mac_addr,
-				   LCS_MAC_LENGTH) == 0 &&
-			    tmp->ipm.ip_addr == im4->multiaddr) {
-				ipm = tmp;
-				break;
-			}
-		}
+		ipm = lcs_check_addr_entry(card, im4, buf);
 		if (ipm != NULL)
 			continue;	/* Address already in list. */
 		ipm = (struct lcs_ipm_list *)
@@ -1043,12 +1231,37 @@
 		memcpy(&ipm->ipm.mac_addr, buf, LCS_MAC_LENGTH);
 		ipm->ipm.ip_addr = im4->multiaddr;
 		ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED;
+		spin_lock_irqsave(&card->ipm_lock, flags);
 		list_add(&ipm->list, &card->ipm_list);
+		spin_unlock_irqrestore(&card->ipm_lock, flags);
 	}
-	spin_unlock(&card->ipm_lock);
+}
+
+static int
+lcs_register_mc_addresses(void *data)
+{
+	struct lcs_card *card;
+	struct in_device *in4_dev;
+
+	card = (struct lcs_card *) data;
+	daemonize("regipm");
+
+	if (!lcs_do_run_thread(card, LCS_SET_MC_THREAD))
+		return 0;
+	LCS_DBF_TEXT(4, trace, "regmulti");
+
+	in4_dev = in_dev_get(card->dev);
+	if (in4_dev == NULL)
+		goto out;
+	read_lock(&in4_dev->mc_list_lock);
+	lcs_remove_mc_addresses(card,in4_dev);
+	lcs_set_mc_addresses(card, in4_dev);
 	read_unlock(&in4_dev->mc_list_lock);
 	in_dev_put(in4_dev);
+
 	lcs_fix_multicast_list(card);
+out:
+	lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD);
 	return 0;
 }
 /**
@@ -1062,8 +1275,10 @@
 
         LCS_DBF_TEXT(4, trace, "setmulti");
         card = (struct lcs_card *) dev->priv;
-        set_bit(3, &card->thread_mask);
-        schedule_work(&card->kernel_thread_starter);
+
+        if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) {
+		schedule_work(&card->kernel_thread_starter);
+	}
 }
 
 #endif /* CONFIG_IP_MULTICAST */
@@ -1427,6 +1642,7 @@
 	return -EIO;
 }
 
+
 /**
  * LCS Stop card
  */
@@ -1440,6 +1656,7 @@
 	if (card->read.state != CH_STATE_STOPPED &&
 	    card->write.state != CH_STATE_STOPPED &&
 	    card->state == DEV_STATE_UP) {
+		lcs_clear_multicast_list(card);
 		rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP);
 		rc = lcs_send_shutdown(card);
 	}
@@ -1459,6 +1676,9 @@
 
 	card = (struct lcs_card *) data;
 	daemonize("lgwstpln");
+
+	if (!lcs_do_run_thread(card, LCS_STARTLAN_THREAD))
+		return 0;
 	LCS_DBF_TEXT(4, trace, "lgwstpln");
 	if (card->dev)
 		netif_stop_queue(card->dev);
@@ -1471,6 +1691,7 @@
 	} else
 		PRINT_ERR("LCS Startlan for device %s failed!\n",
 			  card->dev->name);
+	lcs_clear_thread_running_bit(card, LCS_STARTLAN_THREAD);
 	return 0;
 }
 
@@ -1485,8 +1706,11 @@
 	struct lcs_card *card;
 
 	card = (struct lcs_card *) data;
-	daemonize("lgwstpln");
-	LCS_DBF_TEXT(4, trace, "lgwstpln");
+	daemonize("lgwstaln");
+
+	if (!lcs_do_run_thread(card, LCS_STARTUP_THREAD))
+		return 0;
+	LCS_DBF_TEXT(4, trace, "lgwstaln");
 	if (card->dev)
 		netif_stop_queue(card->dev);
 	rc = lcs_send_startup(card, LCS_INITIATOR_LGW);
@@ -1511,6 +1735,7 @@
 	else
 		PRINT_ERR("LCS Startup for device %s failed!\n",
 			  card->dev->name);
+	lcs_clear_thread_running_bit(card, LCS_STARTUP_THREAD);
 	return 0;
 }
 
@@ -1526,6 +1751,9 @@
 
 	card = (struct lcs_card *) data;
 	daemonize("lgwstop");
+
+	if (!lcs_do_run_thread(card, LCS_STOPLAN_THREAD))
+		return 0;
 	LCS_DBF_TEXT(4, trace, "lgwstop");
 	if (card->dev)
 		netif_stop_queue(card->dev);
@@ -1539,6 +1767,7 @@
         rc = lcs_resetcard(card);
         if (rc != 0)
                 rc = lcs_stopcard(card);
+	lcs_clear_thread_running_bit(card, LCS_STOPLAN_THREAD);
         return rc;
 }
 
@@ -1549,14 +1778,14 @@
 lcs_start_kernel_thread(struct lcs_card *card)
 {
 	LCS_DBF_TEXT(5, trace, "krnthrd");
-	if (test_and_clear_bit(0, &card->thread_mask))
+	if (lcs_do_start_thread(card, LCS_STARTUP_THREAD))
 		kernel_thread(lcs_lgw_startup_thread, (void *) card, SIGCHLD);
-	if (test_and_clear_bit(1, &card->thread_mask))
+	if (lcs_do_start_thread(card, LCS_STARTLAN_THREAD))
 		kernel_thread(lcs_lgw_startlan_thread, (void *) card, SIGCHLD);
-	if (test_and_clear_bit(2, &card->thread_mask))
+	if (lcs_do_start_thread(card, LCS_STOPLAN_THREAD))
 		kernel_thread(lcs_lgw_stoplan_thread, (void *) card, SIGCHLD);
 #ifdef CONFIG_IP_MULTICAST
-	if (test_and_clear_bit(3, &card->thread_mask))
+	if (lcs_do_start_thread(card, LCS_SET_MC_THREAD))
 		kernel_thread(lcs_register_mc_addresses, (void *) card, SIGCHLD);
 #endif
 }
@@ -1571,16 +1800,19 @@
 	if (cmd->initiator == LCS_INITIATOR_LGW) {
 		switch(cmd->cmd_code) {
 		case LCS_CMD_STARTUP:
-			set_bit(0, &card->thread_mask);
-			schedule_work(&card->kernel_thread_starter);
+			if (!lcs_set_thread_start_bit(card,
+						      LCS_STARTUP_THREAD))
+				schedule_work(&card->kernel_thread_starter);
 			break;
 		case LCS_CMD_STARTLAN:
-			set_bit(1, &card->thread_mask);
-			schedule_work(&card->kernel_thread_starter);
+			if (!lcs_set_thread_start_bit(card,
+						      LCS_STARTLAN_THREAD))
+				schedule_work(&card->kernel_thread_starter);
 			break;
 		case LCS_CMD_STOPLAN:
-			set_bit(2, &card->thread_mask);
-			schedule_work(&card->kernel_thread_starter);
+			if (!lcs_set_thread_start_bit(card,
+						      LCS_STOPLAN_THREAD))
+				schedule_work(&card->kernel_thread_starter);
 			break;
 		default:
 			PRINT_INFO("UNRECOGNIZED LGW COMMAND\n");
@@ -1953,7 +2185,9 @@
 		card->dev->set_multicast_list = lcs_set_multicast_list;
 #endif
 	netif_stop_queue(card->dev);
+	lcs_set_allowed_threads(card,0xffffffff);
 	if (recover_state == DEV_STATE_RECOVER) {
+		lcs_set_multicast_list(card->dev);
 		card->dev->flags |= IFF_UP;
 		netif_wake_queue(card->dev);
 		card->state = DEV_STATE_UP;
@@ -1982,7 +2216,9 @@
 	card = (struct lcs_card *)ccwgdev->dev.driver_data;
 	if (!card)
 		return -ENODEV;
-
+	lcs_set_allowed_threads(card, 0);
+	if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
+		return -ERESTARTSYS;
 	LCS_DBF_HEX(3, setup, &card, sizeof(void*));
 	recover_state = card->state;
 
diff -Nru a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
--- a/drivers/s390/net/lcs.h	2004-07-01 22:23:50 -07:00
+++ b/drivers/s390/net/lcs.h	2004-08-27 00:02:35 -07:00
@@ -6,7 +6,7 @@
 #include <linux/workqueue.h>
 #include <asm/ccwdev.h>
 
-#define VERSION_LCS_H "$Revision: 1.17 $"
+#define VERSION_LCS_H "$Revision: 1.18 $"
 
 #define LCS_DBF_TEXT(level, name, text) \
 	do { \
@@ -152,6 +152,12 @@
 	DEV_STATE_RECOVER,
 };
 
+enum lcs_threads {
+	LCS_SET_MC_THREAD 	= 1,
+	LCS_STARTLAN_THREAD	= 2,
+	LCS_STOPLAN_THREAD	= 4,
+	LCS_STARTUP_THREAD	= 8,
+};
 /**
  * LCS struct declarations
  */
@@ -247,9 +253,11 @@
 struct lcs_reply {
 	struct list_head list;
 	__u16 sequence_no;
+	atomic_t refcnt;
 	/* Callback for completion notification. */
 	void (*callback)(struct lcs_card *, struct lcs_cmd *);
 	wait_queue_head_t wait_q;
+	struct lcs_card *card;
 	int received;
 	int rc;
 };
@@ -268,6 +276,7 @@
 	int buf_idx;
 };
 
+
 /**
  * definition of the lcs card
  */
@@ -287,7 +296,11 @@
 	int lancmd_timeout;
 
 	struct work_struct kernel_thread_starter;
-	unsigned long thread_mask;
+	spinlock_t mask_lock;
+	unsigned long thread_start_mask;
+	unsigned long thread_running_mask;
+	unsigned long thread_allowed_mask;
+	wait_queue_head_t wait_q;
 
 #ifdef CONFIG_IP_MULTICAST
 	struct list_head ipm_list;
diff -Nru a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
--- a/drivers/s390/net/qeth_main.c	2004-08-15 19:53:29 -07:00
+++ b/drivers/s390/net/qeth_main.c	2004-08-27 00:02:36 -07:00
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.130 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.132 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.130 $	 $Date: 2004/08/05 11:21:50 $
+ *    $Revision: 1.132 $	 $Date: 2004/08/19 12:39:43 $
  *
  * 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
@@ -79,7 +79,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-#define VERSION_QETH_C "$Revision: 1.130 $"
+#define VERSION_QETH_C "$Revision: 1.132 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -4547,7 +4547,8 @@
 	if (!card)
 		return -ENODEV;
 
-	if (card->state != CARD_STATE_UP)
+	if ((card->state != CARD_STATE_UP) &&
+            (card->state != CARD_STATE_SOFTSETUP))
 		return -ENODEV;
 
 	switch (cmd){
diff -Nru a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
--- a/drivers/s390/scsi/zfcp_aux.c	2004-08-07 11:05:36 -07:00
+++ b/drivers/s390/scsi/zfcp_aux.c	2004-08-24 02:09:01 -07:00
@@ -29,7 +29,7 @@
  */
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_AUX_REVISION "$Revision: 1.115 $"
+#define ZFCP_AUX_REVISION "$Revision: 1.121 $"
 
 #include "zfcp_ext.h"
 
@@ -48,10 +48,10 @@
 
 static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
 static inline int zfcp_sg_list_free(struct zfcp_sg_list *);
-static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, void *,
-					      size_t);
-static inline int zfcp_sg_list_copy_to_user(void *, struct zfcp_sg_list *,
-					    size_t);
+static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
+					      void __user *, size_t);
+static inline int zfcp_sg_list_copy_to_user(void __user *,
+					    struct zfcp_sg_list *, size_t);
 
 static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *,
 	unsigned int, unsigned long);
@@ -95,7 +95,7 @@
 module_param(loglevel, uint, 0);
 MODULE_PARM_DESC(loglevel,
 		 "log levels, 8 nibbles: "
-		 "(unassigned) ERP QDIO DIO Config FSF SCSI Other, "
+		 "(unassigned) FC ERP QDIO CIO Config FSF SCSI Other, "
 		 "levels: 0=none 1=normal 2=devel 3=trace");
 
 #ifdef ZFCP_PRINT_FLAGS
@@ -382,7 +382,7 @@
 zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                     unsigned int command, unsigned long buffer)
 {
-	struct zfcp_cfdc_sense_data sense_data, *sense_data_user;
+	struct zfcp_cfdc_sense_data sense_data, __user *sense_data_user;
 	struct zfcp_adapter *adapter = NULL;
 	struct zfcp_fsf_req *fsf_req = NULL;
 	struct zfcp_sg_list *sg_list = NULL;
@@ -403,7 +403,7 @@
 		goto out;
 	}
 
-	if ((sense_data_user = (struct zfcp_cfdc_sense_data*)buffer) == NULL) {
+	if ((sense_data_user = (void __user *) buffer) == NULL) {
 		ZFCP_LOG_INFO("sense data record is required\n");
 		retval = -EINVAL;
 		goto out;
@@ -520,6 +520,12 @@
 	wait_event(fsf_req->completion_wq,
 	           fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
 
+	if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
+	    (fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
+		retval = -ENXIO;
+		goto out;
+	}
+
 	sense_data.fsf_status = fsf_req->qtcb->header.fsf_status;
 	memcpy(&sense_data.fsf_status_qual,
 	       &fsf_req->qtcb->header.fsf_status_qual,
@@ -637,7 +643,8 @@
  *              -EFAULT - Memory I/O operation fault
  */
 static inline int
-zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer,
+zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
+			    void __user *user_buffer,
                             size_t size)
 {
 	struct scatterlist *sg;
@@ -671,7 +678,8 @@
  *              -EFAULT - Memory I/O operation fault
  */
 static inline int
-zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list,
+zfcp_sg_list_copy_to_user(void __user  *user_buffer,
+			  struct zfcp_sg_list *sg_list,
                           size_t size)
 {
 	struct scatterlist *sg;
@@ -1646,15 +1654,7 @@
 	ct_iu_req = zfcp_sg_to_address(ct->req);
 	ct_iu_resp = zfcp_sg_to_address(ct->resp);
 
-        if (ct_iu_resp->header.revision != ZFCP_CT_REVISION)
-		goto failed;
-        if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE)
-		goto failed;
-        if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER)
-		goto failed;
-        if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS)
-		goto failed;
-        if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) {
+	if (zfcp_check_ct_response(&ct_iu_resp->header)) {
 		/* FIXME: do we need some specific erp entry points */
 		atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
 		goto failed;
@@ -1675,7 +1675,7 @@
 		       zfcp_get_busid_by_port(port), port->wwpn, port->d_id);
 	goto out;
 
-failed:
+ failed:
 	ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn "
 			"0x%016Lx for adapter %s\n",
 			port->wwpn, zfcp_get_busid_by_port(port));
@@ -1688,6 +1688,171 @@
  out:
         zfcp_gid_pn_buffers_free(gid_pn);
 	return;
+}
+
+/* reject CT_IU reason codes acc. to FC-GS-4 */
+static const struct zfcp_rc_entry zfcp_ct_rc[] = {
+	{0x01, "invalid command code"},
+	{0x02, "invalid version level"},
+	{0x03, "logical error"},
+	{0x04, "invalid CT_IU size"},
+	{0x05, "logical busy"},
+	{0x07, "protocol error"},
+	{0x09, "unable to perform command request"},
+	{0x0b, "command not supported"},
+	{0x0d, "server not available"},
+	{0x0e, "session could not be established"},
+	{0xff, "vendor specific error"},
+	{0, NULL},
+};
+
+/* LS_RJT reason codes acc. to FC-FS */
+static const struct zfcp_rc_entry zfcp_ls_rjt_rc[] = {
+	{0x01, "invalid LS_Command code"},
+	{0x03, "logical error"},
+	{0x05, "logical busy"},
+	{0x07, "protocol error"},
+	{0x09, "unable to perform command request"},
+	{0x0b, "command not supported"},
+	{0x0e, "command already in progress"},
+	{0xff, "vendor specific error"},
+	{0, NULL},
+};
+
+/* reject reason codes according to FC-PH/FC-FS */
+static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = {
+	{0x01, "invalid D_ID"},
+	{0x02, "invalid S_ID"},
+	{0x03, "Nx_Port not available, temporary"},
+	{0x04, "Nx_Port not available, permament"},
+	{0x05, "class not supported"},
+	{0x06, "delimiter usage error"},
+	{0x07, "TYPE not supported"},
+	{0x08, "invalid Link_Control"},
+	{0x09, "invalid R_CTL field"},
+	{0x0a, "invalid F_CTL field"},
+	{0x0b, "invalid OX_ID"},
+	{0x0c, "invalid RX_ID"},
+	{0x0d, "invalid SEQ_ID"},
+	{0x0e, "invalid DF_CTL"},
+	{0x0f, "invalid SEQ_CNT"},
+	{0x10, "invalid parameter field"},
+	{0x11, "exchange error"},
+	{0x12, "protocol error"},
+	{0x13, "incorrect length"},
+	{0x14, "unsupported ACK"},
+	{0x15, "class of service not supported by entity at FFFFFE"},
+	{0x16, "login required"},
+	{0x17, "excessive sequences attempted"},
+	{0x18, "unable to establish exchange"},
+	{0x1a, "fabric path not available"},
+	{0x1b, "invalid VC_ID (class 4)"},
+	{0x1c, "invalid CS_CTL field"},
+	{0x1d, "insufficient resources for VC (class 4)"},
+	{0x1f, "invalid class of service"},
+	{0x20, "preemption request rejected"},
+	{0x21, "preemption not enabled"},
+	{0x22, "multicast error"},
+	{0x23, "multicast error terminate"},
+	{0x24, "process login required"},
+	{0xff, "vendor specific reject"},
+	{0, NULL},
+};
+
+/**
+ * zfcp_rc_description - return description for given reaon code
+ * @code: reason code
+ * @rc_table: table of reason codes and descriptions
+ */
+static inline const char *
+zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table)
+{
+	const char *descr = "unknown reason code";
+
+	do {
+		if (code == rc_table->code) {
+			descr = rc_table->description;
+			break;
+		}
+		rc_table++;
+	} while (rc_table->code && rc_table->description);
+
+	return descr;
+}
+
+/**
+ * zfcp_check_ct_response - evaluate reason code for CT_IU
+ * @rjt: response payload to an CT_IU request
+ * Return: 0 for accept CT_IU, 1 for reject CT_IU or invlid response code
+ */
+int
+zfcp_check_ct_response(struct ct_hdr *rjt)
+{
+	if (rjt->cmd_rsp_code == ZFCP_CT_ACCEPT)
+		return 0;
+
+	if (rjt->cmd_rsp_code != ZFCP_CT_REJECT) {
+		ZFCP_LOG_NORMAL("error: invalid Generic Service command/"
+				"response code (0x%04hx)\n",
+				rjt->cmd_rsp_code);
+		return 1;
+	}
+
+	ZFCP_LOG_INFO("Generic Service command rejected\n");
+	ZFCP_LOG_INFO("%s (0x%02x, 0x%02x, 0x%02x)\n",
+		      zfcp_rc_description(rjt->reason_code, zfcp_ct_rc),
+		      (u32) rjt->reason_code, (u32) rjt->reason_code_expl,
+		      (u32) rjt->vendor_unique);
+
+	return 1;
+}
+
+/**
+ * zfcp_print_els_rjt - print reject parameter and description for ELS reject
+ * @rjt_par: reject parameter acc. to FC-PH/FC-FS
+ * @rc_table: table of reason codes and descriptions
+ */
+static inline void
+zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par,
+		   const struct zfcp_rc_entry *rc_table)
+{
+	ZFCP_LOG_INFO("%s (%02x %02x %02x %02x)\n",
+		      zfcp_rc_description(rjt_par->reason_code, rc_table),
+		      (u32) rjt_par->action, (u32) rjt_par->reason_code,
+		      (u32) rjt_par->reason_expl, (u32) rjt_par->vendor_unique);
+}
+
+/**
+ * zfcp_fsf_handle_els_rjt - evaluate status qualifier/reason code on ELS reject
+ * @sq: status qualifier word
+ * @rjt_par: reject parameter as described in FC-PH and FC-FS
+ * Return: -EROMTEIO for LS_RJT, -EREMCHG for invalid D_ID, -EIO else
+ */
+int
+zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par)
+{
+	int ret = -EIO;
+
+	if (sq == FSF_IOSTAT_NPORT_RJT) {
+		ZFCP_LOG_INFO("ELS rejected (P_RJT)\n");
+		zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc);
+		/* invalid d_id */
+		if (rjt_par->reason_code == 0x01)
+			ret = -EREMCHG;
+	} else if (sq == FSF_IOSTAT_FABRIC_RJT) {
+		ZFCP_LOG_INFO("ELS rejected (F_RJT)\n");
+		zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc);
+		/* invalid d_id */
+		if (rjt_par->reason_code == 0x01)
+			ret = -EREMCHG;
+	} else if (sq == FSF_IOSTAT_LS_RJT) {
+		ZFCP_LOG_INFO("ELS rejected (LS_RJT)\n");
+		zfcp_print_els_rjt(rjt_par, zfcp_ls_rjt_rc);
+		ret = -EREMOTEIO;
+	} else
+		ZFCP_LOG_INFO("unexpected SQ: 0x%02x\n", sq);
+
+	return ret;
 }
 
 #undef ZFCP_LOG_AREA
diff -Nru a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
--- a/drivers/s390/scsi/zfcp_def.h	2004-08-07 11:05:36 -07:00
+++ b/drivers/s390/scsi/zfcp_def.h	2004-08-24 02:09:01 -07:00
@@ -33,7 +33,7 @@
 #define ZFCP_DEF_H
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_DEF_REVISION "$Revision: 1.81 $"
+#define ZFCP_DEF_REVISION "$Revision: 1.83 $"
 
 /*************************** INCLUDES *****************************************/
 
@@ -296,13 +296,11 @@
 #define ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED	0x0B
 #define ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR		0xFF
 
-struct zfcp_ls_rjt {
-	u8		code;
-	u8		field[3];
-	u8		reserved;
-	u8	reason_code;
-	u8		reason_expl;
-	u8	vendor_unique;
+struct zfcp_ls_rjt_par {
+	u8 action;
+ 	u8 reason_code;
+ 	u8 reason_expl;
+ 	u8 vendor_unique;
 } __attribute__ ((packed));
 
 struct zfcp_ls_rtv {
@@ -423,6 +421,11 @@
 			specific_id;
 } __attribute__((packed));
 
+struct zfcp_rc_entry {
+	u8 code;
+	const char *description;
+};
+
 /*
  * FC-GS-2 stuff
  */
@@ -431,9 +434,9 @@
 #define ZFCP_CT_NAME_SERVER		0x02
 #define ZFCP_CT_SYNCHRONOUS		0x00
 #define ZFCP_CT_GID_PN			0x0121
-#define ZFCP_CT_GA_NXT			0x0100
 #define ZFCP_CT_MAX_SIZE		0x1020
 #define ZFCP_CT_ACCEPT			0x8002
+#define ZFCP_CT_REJECT			0x8001
 
 /*
  * FC-GS-4 stuff
@@ -851,7 +854,7 @@
         struct zfcp_port *port;
 };
 
-typedef int (*zfcp_send_els_handler_t)(unsigned long);
+typedef void (*zfcp_send_els_handler_t)(unsigned long);
 
 /* used to pass parameters to zfcp_send_els() */
 /* ToDo merge send_ct() and send_els() and corresponding structs */
diff -Nru a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
--- a/drivers/s390/scsi/zfcp_erp.c	2004-08-07 11:05:36 -07:00
+++ b/drivers/s390/scsi/zfcp_erp.c	2004-08-24 02:09:01 -07:00
@@ -31,12 +31,12 @@
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_ERP
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_ERP_REVISION "$Revision: 1.61 $"
+#define ZFCP_ERP_REVISION "$Revision: 1.62 $"
 
 #include "zfcp_ext.h"
 
 static int zfcp_els(struct zfcp_port *, u8);
-static int zfcp_els_handler(unsigned long);
+static void zfcp_els_handler(unsigned long);
 
 static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
 static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int);
@@ -324,6 +324,7 @@
 	send_els->completion = NULL;
 
 	req = zfcp_sg_to_address(send_els->req);
+	memset(req, 0, PAGE_SIZE);
 
 	*(u32*)req = 0;
 	*(u8*)req = ls_code;
@@ -412,185 +413,99 @@
 }
 
 
-/*
- * function:    zfcp_els_handler
- *
- * purpose:     Handler for all kind of ELSs
- *
- * returns:     0       - Operation completed successfuly
- *              -ENXIO  - ELS has been rejected
- *              -EPERM  - Port forced reopen failed
+/**
+ * zfcp_els_handler - handler for ELS commands
+ * @data: pointer to struct zfcp_send_els
+ * If ELS failed (LS_RJT or timed out) forced reopen of the port is triggered.
  */
-int
+void
 zfcp_els_handler(unsigned long data)
 {
 	struct zfcp_send_els *send_els = (struct zfcp_send_els*)data;
 	struct zfcp_port *port = send_els->port;
-	struct zfcp_ls_rjt *rjt;
 	struct zfcp_ls_rtv_acc *rtv;
 	struct zfcp_ls_rls_acc *rls;
 	struct zfcp_ls_pdisc_acc *pdisc;
 	struct zfcp_ls_adisc_acc *adisc;
 	void *req, *resp;
-	u8 req_code, resp_code;
-	int retval = 0;
+	u8 req_code;
 
+	/* request rejected or timed out */
 	if (send_els->status != 0) {
 		ZFCP_LOG_NORMAL("ELS request timed out, force physical port "
 				"reopen of port 0x%016Lx on adapter %s\n",
 				port->wwpn, zfcp_get_busid_by_port(port));
 		debug_text_event(port->adapter->erp_dbf, 3, "forcreop");
-		retval = zfcp_erp_port_forced_reopen(port, 0);
-		if (retval != 0) {
+		if (zfcp_erp_port_forced_reopen(port, 0))
 			ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx "
 					"on adapter %s failed\n", port->wwpn,
 					zfcp_get_busid_by_port(port));
-			retval = -EPERM;
-		}
-		goto skip_fsfstatus;
+		goto out;
 	}
 
-	req = (void*)((page_to_pfn(send_els->req->page) << PAGE_SHIFT) + send_els->req->offset);
-	resp = (void*)((page_to_pfn(send_els->resp->page) << PAGE_SHIFT) + send_els->resp->offset);
+	req = zfcp_sg_to_address(send_els->req);
+	resp = zfcp_sg_to_address(send_els->resp);
 	req_code = *(u8*)req;
-	resp_code = *(u8*)resp;
-
-	switch (resp_code) {
-
-	case ZFCP_LS_RJT:
-		rjt = (struct zfcp_ls_rjt*)resp;
 
-		switch (rjt->reason_code) {
+	switch (req_code) {
 
-		case ZFCP_LS_RJT_INVALID_COMMAND_CODE:
-			ZFCP_LOG_INFO("invalid LS command code "
-				      "(wwpn=0x%016Lx, command=0x%02x)\n",
-				      port->wwpn, req_code);
-			break;
-
-		case ZFCP_LS_RJT_LOGICAL_ERROR:
-			ZFCP_LOG_INFO("logical error (wwpn=0x%016Lx, "
-				      "reason_expl=0x%02x)\n",
-				      port->wwpn, rjt->reason_expl);
-			break;
-
-		case ZFCP_LS_RJT_LOGICAL_BUSY:
-			ZFCP_LOG_INFO("logical busy (wwpn=0x%016Lx, "
-				      "reason_expl=0x%02x)\n",
-				      port->wwpn, rjt->reason_expl);
-			break;
-
-		case ZFCP_LS_RJT_PROTOCOL_ERROR:
-			ZFCP_LOG_INFO("protocol error (wwpn=0x%016Lx, "
-				      "reason_expl=0x%02x)\n",
-				      port->wwpn, rjt->reason_expl);
-			break;
-
-		case ZFCP_LS_RJT_UNABLE_TO_PERFORM:
-			ZFCP_LOG_INFO("unable to perform command requested "
-				      "(wwpn=0x%016Lx, reason_expl=0x%02x)\n",
-				      port->wwpn, rjt->reason_expl);
-			break;
-
-		case ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED:
-			ZFCP_LOG_INFO("command not supported (wwpn=0x%016Lx, "
-				      "command=0x%02x)\n",
-				      port->wwpn, req_code);
-			break;
-
-		case ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR:
-			ZFCP_LOG_INFO("vendor specific error (wwpn=0x%016Lx, "
-				      "vendor_unique=0x%02x)\n",
-				      port->wwpn, rjt->vendor_unique);
-			break;
-
-		default:
-			ZFCP_LOG_NORMAL("ELS rejected by remote port 0x%016Lx "
-					"on adapter %s (reason_code=0x%02x)\n",
-					port->wwpn,
-					zfcp_get_busid_by_port(port),
-					rjt->reason_code);
-		}
-		retval = -ENXIO;
+	case ZFCP_LS_RTV:
+		rtv = (struct zfcp_ls_rtv_acc*)resp;
+		ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id "
+			      "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n",
+			      port->d_id, port->adapter->s_id,
+			      rtv->r_a_tov, rtv->e_d_tov,
+			      rtv->qualifier &
+			      ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm');
 		break;
 
-	case ZFCP_LS_ACC:
-		switch (req_code) {
+	case ZFCP_LS_RLS:
+		rls = (struct zfcp_ls_rls_acc*)resp;
+		ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id "
+			      "0x%08x (link_failure_count=%u, "
+			      "loss_of_sync_count=%u, "
+			      "loss_of_signal_count=%u, "
+			      "primitive_sequence_protocol_error=%u, "
+			      "invalid_transmition_word=%u, "
+			      "invalid_crc_count=%u)\n",
+			      port->d_id, port->adapter->s_id,
+			      rls->link_failure_count,
+			      rls->loss_of_sync_count,
+			      rls->loss_of_signal_count,
+			      rls->prim_seq_prot_error,
+			      rls->invalid_transmition_word,
+			      rls->invalid_crc_count);
+		break;
 
-		case ZFCP_LS_RTV:
-			rtv = (struct zfcp_ls_rtv_acc*)resp;
-			ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id "
-				      "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n",
-				      port->d_id, port->adapter->s_id,
-				      rtv->r_a_tov, rtv->e_d_tov,
-				      rtv->qualifier &
-				      ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm');
-			break;
-
-		case ZFCP_LS_RLS:
-			rls = (struct zfcp_ls_rls_acc*)resp;
-			ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id "
-				      "0x%08x (link_failure_count=%u, "
-				      "loss_of_sync_count=%u, "
-				      "loss_of_signal_count=%u, "
-				      "primitive_sequence_protocol_error=%u, "
-				      "invalid_transmition_word=%u, "
-				      "invalid_crc_count=%u)\n",
-				      port->d_id, port->adapter->s_id,
-				      rls->link_failure_count,
-				      rls->loss_of_sync_count,
-				      rls->loss_of_signal_count,
-				      rls->prim_seq_prot_error,
-				      rls->invalid_transmition_word,
-				      rls->invalid_crc_count);
-			break;
-
-		case ZFCP_LS_PDISC:
-			pdisc = (struct zfcp_ls_pdisc_acc*)resp;
-			ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id "
-				      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
-				      "vendor='%-16s')\n", port->d_id,
-				      port->adapter->s_id, pdisc->wwpn,
-				      pdisc->wwnn, pdisc->vendor_version);
-			break;
-
-		case ZFCP_LS_ADISC:
-			adisc = (struct zfcp_ls_adisc_acc*)resp;
-			ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
-				      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
-				      "hard_nport_id=0x%08x, "
-				      "nport_id=0x%08x)\n", port->d_id,
-				      port->adapter->s_id, adisc->wwpn,
-				      adisc->wwnn, adisc->hard_nport_id,
-				      adisc->nport_id);
-			/* FIXME: set wwnn in during open port */
-			if (port->wwnn == 0)
-				port->wwnn = adisc->wwnn;
-			break;
-		}
+	case ZFCP_LS_PDISC:
+		pdisc = (struct zfcp_ls_pdisc_acc*)resp;
+		ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id "
+			      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
+			      "vendor='%-16s')\n", port->d_id,
+			      port->adapter->s_id, pdisc->wwpn,
+			      pdisc->wwnn, pdisc->vendor_version);
 		break;
 
-	default:
-		ZFCP_LOG_NORMAL("unknown payload code 0x%02x received for "
-				"request 0x%02x to d_id 0x%08x, reopen needed "
-				"for port 0x%016Lx on adapter %s\n", resp_code,
-				req_code, port->d_id,  port->wwpn,
-				zfcp_get_busid_by_port(port));
-		retval = zfcp_erp_port_forced_reopen(port, 0);
-		if (retval != 0) {
-			ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx on "
-					"adapter %s failed\n", port->wwpn,
-					zfcp_get_busid_by_port(port));
-			retval = -EPERM;
-		}
+	case ZFCP_LS_ADISC:
+		adisc = (struct zfcp_ls_adisc_acc*)resp;
+		ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
+			      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
+			      "hard_nport_id=0x%08x, "
+			      "nport_id=0x%08x)\n", port->d_id,
+			      port->adapter->s_id, adisc->wwpn,
+			      adisc->wwnn, adisc->hard_nport_id,
+			      adisc->nport_id);
+		/* FIXME: set wwnn in during open port */
+		if (port->wwnn == 0)
+			port->wwnn = adisc->wwnn;
+		break;
 	}
 
-skip_fsfstatus:
+ out:
 	__free_pages(send_els->req->page, 0);
 	kfree(send_els->req);
 	kfree(send_els->resp);
-
-	return retval;
+	kfree(send_els);
 }
 
 
diff -Nru a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
--- a/drivers/s390/scsi/zfcp_ext.h	2004-07-01 22:23:51 -07:00
+++ b/drivers/s390/scsi/zfcp_ext.h	2004-08-24 02:09:01 -07:00
@@ -31,7 +31,7 @@
 #ifndef ZFCP_EXT_H
 #define ZFCP_EXT_H
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_EXT_REVISION "$Revision: 1.51 $"
+#define ZFCP_EXT_REVISION "$Revision: 1.53 $"
 
 #include "zfcp_def.h"
 
@@ -117,9 +117,11 @@
 extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(
 	unsigned long, struct zfcp_adapter *, struct zfcp_unit *, int);
 
-/******************************** FCP ****************************************/
+/******************************* FC/FCP **************************************/
 extern int  zfcp_nameserver_enqueue(struct zfcp_adapter *);
 extern int  zfcp_ns_gid_pn_request(struct zfcp_erp_action *);
+extern int  zfcp_check_ct_response(struct ct_hdr *);
+extern int  zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *);
 
 /******************************* SCSI ****************************************/
 extern int  zfcp_adapter_scsi_register(struct zfcp_adapter *);
diff -Nru a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
--- a/drivers/s390/scsi/zfcp_fsf.c	2004-08-07 11:05:36 -07:00
+++ b/drivers/s390/scsi/zfcp_fsf.c	2004-08-24 02:09:01 -07:00
@@ -29,7 +29,7 @@
  */
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_FSF_C_REVISION "$Revision: 1.55 $"
+#define ZFCP_FSF_C_REVISION "$Revision: 1.59 $"
 
 #include "zfcp_ext.h"
 
@@ -48,7 +48,7 @@
 static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *);
-static inline int zfcp_fsf_req_create_sbal_check(
+static inline int zfcp_fsf_req_sbal_check(
 	unsigned long *, struct zfcp_qdio_queue *, int);
 static inline int zfcp_use_one_sbal(
 	struct scatterlist *, int, struct scatterlist *, int);
@@ -79,10 +79,9 @@
 };
 
 static const char zfcp_act_subtable_type[5][8] = {
-	{"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"}
+	"unknown", "OS", "WWPN", "DID", "LUN"
 };
 
-
 /****************************************************************/
 /*************** FSF related Functions  *************************/
 /****************************************************************/
@@ -1863,6 +1862,10 @@
 			/* ERP strategy will escalate */
 			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+			retval =
+			  zfcp_handle_els_rjt(header->fsf_status_qual.word[1],
+					      (struct zfcp_ls_rjt_par *)
+					      &header->fsf_status_qual.word[2]);
 			break;
 		case FSF_SQ_RETRY_IF_POSSIBLE:
 			ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n");
@@ -1971,8 +1974,6 @@
 	if (send_els->handler != 0)
 		send_els->handler(send_els->handler_data);
 
-	kfree(send_els);
-
 	return retval;
 }
 
@@ -4157,87 +4158,6 @@
 	}
 
  skip_fsfstatus:
-#if 0
-	/*
-	 * This nasty chop at the problem is not working anymore
-	 * as we do not adjust the retry count anylonger in order
-	 * to have a number of retries that avoids I/O errors.
-	 * The manipulation of the retry count has been removed
-	 * in favour of a safe tape device handling. We must not
-	 * sent SCSI commands more than once to a device if no
-	 * retries are permitted by the high level driver. Generally
-	 * speaking, it was a mess to change retry counts. So it is
-	 * fine that this sort of workaround is gone.
-	 * Then, we had to face a certain number of immediate retries in case of
-	 * busy and queue full conditions (see below).
-	 * This is not acceptable
-	 * for the latter. Queue full conditions are used
-	 * by devices to indicate to a host that the host can rely
-	 * on the completion (or timeout) of at least one outstanding
-	 * command as a suggested trigger for command retries.
-	 * Busy conditions require a different trigger since
-	 * no commands are outstanding for that initiator from the
-	 * devices perspective.
-	 * The drawback of mapping a queue full condition to a
-	 * busy condition is the chance of wasting all retries prior
-	 * to the time when the device indicates that a command
-	 * rejected due to a queue full condition should be re-driven.
-	 * This case would lead to unnecessary I/O errors that
-	 * have to be considered fatal if for example ext3's
-	 * journaling would be torpedoed by such an avoidable
-	 * I/O error.
-	 * So, what issues are there with not mapping a queue-full
-	 * condition to a busy condition?
-	 * Due to the 'exclusive LUN'
-	 * policy enforced by the zSeries FCP channel, this 
-	 * Linux instance is the only initiator with regard to
-	 * this adapter. It is safe to rely on the information
-	 * 'don't disturb me now ... and btw. no other commands
-	 * pending for you' (= queue full) sent by the LU,
-	 * since no other Linux can use this LUN via this adapter
-	 * at the same time. If there is a potential race
-	 * introduced by the FCP channel by not inhibiting Linux A
-	 * to give up a LU with commands pending while Linux B
-	 * grabs this LU and sends commands  - thus providing
-	 * an exploit at the 'exclusive LUN' policy - then this
-	 * issue has to be considered a hardware problem. It should
-	 * be tracked as such if it really occurs. Even if the
-	 * FCP Channel spec. begs exploiters to wait for the
-	 * completion of all request sent to a LU prior to
-	 * closing this LU connection.
-	 * This spec. statement in conjunction with
-	 * the 'exclusive LUN' policy is not consistent design.
-	 * Another issue is how resource constraints for SCSI commands
-	 * might be handled by the FCP channel (just guessing for now).
-	 * If the FCP channel would always map resource constraints,
-	 * e.g. no free FC exchange ID due to I/O stress caused by
-	 * other sharing Linux instances, to faked queue-full
-	 * conditions then this would be a misinterpretation and
-	 * violation of SCSI standards.
-	 * If there are SCSI stack races as indicated below
-	 * then they need to be fixed just there.
-	 * Providing all issue above are not applicable or will
-	 * be fixed appropriately, removing the following hack
-	 * is the right thing to do.
-	 */
-
-	/*
-	 * Note: This is a rather nasty chop at the problem. We cannot 
-	 * risk adding to the mlqueue however as this will block the 
-	 * device. If it is the last outstanding command for this host
-	 * it will remain blocked indefinitely. This would be quite possible
-	 * on the zSeries FCP adapter.
-	 * Also, there exists a race with scsi_insert_special relying on 
-	 * scsi_request_fn to recalculate some command data which may not 
-	 * happen when q->plugged is true in scsi_request_fn
-	 */
-	if (status_byte(scpnt->result) == QUEUE_FULL) {
-		ZFCP_LOG_DEBUG("Changing QUEUE_FULL to BUSY....\n");
-		scpnt->result &= ~(QUEUE_FULL << 1);
-		scpnt->result |= (BUSY << 1);
-	}
-#endif
-
 	ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
 
 	zfcp_cmd_dbf_event_scsi("response", scpnt);
@@ -4682,8 +4602,8 @@
 }
 
 static inline int
-zfcp_fsf_req_create_sbal_check(unsigned long *flags,
-			       struct zfcp_qdio_queue *queue, int needed)
+zfcp_fsf_req_sbal_check(unsigned long *flags,
+			struct zfcp_qdio_queue *queue, int needed)
 {
 	write_lock_irqsave(&queue->queue_lock, *flags);
 	if (likely(atomic_read(&queue->free_count) >= needed))
@@ -4713,29 +4633,24 @@
  * @adapter: adapter for which request queue is examined
  * @req_flags: flags indicating whether to wait for needed SBAL or not
  * @lock_flags: lock_flags is queue_lock is taken
- *
- * locking: on success the queue_lock for the request queue of the adapter
- *	is held
+ * Return: 0 on success, otherwise -EIO, or -ERESTARTSYS
+ * Locks: lock adapter->request_queue->queue_lock on success
  */
 static int
 zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags,
 		      unsigned long *lock_flags)
 {
-        int condition;
+        long ret;
         struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
 
         if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) {
-                wait_event_interruptible_timeout(adapter->request_wq,
-						 (condition =
-						  zfcp_fsf_req_create_sbal_check
-						  (lock_flags, req_queue, 1)),
-						 ZFCP_SBAL_TIMEOUT);
-                if (!condition) {
-                        return -EIO;
-		}
-        } else if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) {
+                ret = wait_event_interruptible_timeout(adapter->request_wq,
+			zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1),
+						       ZFCP_SBAL_TIMEOUT);
+		if (ret < 0)
+			return ret;
+        } else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1))
                 return -EIO;
-	}
 
         return 0;
 }
diff -Nru a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
--- a/drivers/s390/scsi/zfcp_fsf.h	2004-04-12 10:55:15 -07:00
+++ b/drivers/s390/scsi/zfcp_fsf.h	2004-08-24 02:09:01 -07:00
@@ -227,6 +227,10 @@
 #define FSF_HBA_PORTSTATE_LINKDOWN		0x00000006
 #define FSF_HBA_PORTSTATE_ERROR			0x00000007
 
+/* IO states of adapter */
+#define FSF_IOSTAT_NPORT_RJT			0x00000004
+#define FSF_IOSTAT_FABRIC_RJT			0x00000005
+#define FSF_IOSTAT_LS_RJT			0x00000009
 
 struct fsf_queue_designator;
 struct fsf_status_read_buffer;
diff -Nru a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
--- a/drivers/s390/scsi/zfcp_scsi.c	2004-07-01 22:23:51 -07:00
+++ b/drivers/s390/scsi/zfcp_scsi.c	2004-08-24 02:09:01 -07:00
@@ -31,7 +31,7 @@
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_SCSI
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_SCSI_REVISION "$Revision: 1.65 $"
+#define ZFCP_SCSI_REVISION "$Revision: 1.66 $"
 
 #include "zfcp_ext.h"
 
@@ -430,7 +430,7 @@
 	u64 dbf_fsf_req = 0;
 	u64 dbf_fsf_status = 0;
 	u64 dbf_fsf_qual[2] = { 0, 0 };
-	char dbf_result[ZFCP_ABORT_DBF_LENGTH] = { "##undef" };
+	char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef";
 
 	memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH);
 	memcpy(dbf_opcode,
diff -Nru a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c	2004-05-19 09:03:01 -07:00
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c	2004-08-24 02:09:01 -07:00
@@ -26,18 +26,18 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.33 $"
+#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.36 $"
 
 #include "zfcp_ext.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
 
 static const char fc_topologies[5][25] = {
-	{"<error>"},
-	{"point-to-point"},
-	{"fabric"},
-	{"arbitrated loop"},
-	{"fabric (virt. adapter)"}
+	"<error>",
+	"point-to-point",
+	"fabric",
+	"arbitrated loop",
+	"fabric (virt. adapter)"
 };
 
 /**
@@ -74,29 +74,8 @@
 			 adapter->hardware_version);
 ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number);
 ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
-
-/**
- * zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- *
- * Show function of "in_recovery" attribute of adapter. Will be
- * "0" if no error recovery is pending for adapter, otherwise "1".
- */
-static ssize_t
-zfcp_sysfs_adapter_in_recovery_show(struct device *dev, char *buf)
-{
-	struct zfcp_adapter *adapter;
-
-	adapter = dev_get_drvdata(dev);
-	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status))
-		return sprintf(buf, "1\n");
-	else
-		return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(in_recovery, S_IRUGO,
-		   zfcp_sysfs_adapter_in_recovery_show, NULL);
+ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
+			 (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
 
 /**
  * zfcp_sysfs_port_add_store - add a port to sysfs tree
@@ -138,7 +117,7 @@
 	zfcp_port_put(port);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 static DEVICE_ATTR(port_add, S_IWUSR, NULL, zfcp_sysfs_port_add_store);
@@ -197,7 +176,7 @@
 	zfcp_port_dequeue(port);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 static DEVICE_ATTR(port_remove, S_IWUSR, NULL, zfcp_sysfs_port_remove_store);
@@ -241,7 +220,7 @@
 	zfcp_erp_wait(adapter);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 /**
diff -Nru a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c
--- a/drivers/s390/scsi/zfcp_sysfs_driver.c	2004-05-19 09:03:01 -07:00
+++ b/drivers/s390/scsi/zfcp_sysfs_driver.c	2004-08-24 02:09:01 -07:00
@@ -26,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.14 $"
+#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.15 $"
 
 #include "zfcp_ext.h"
 
@@ -65,7 +65,7 @@
 static ssize_t zfcp_sysfs_loglevel_##_name##_show(struct device_driver *dev,  \
 						  char *buf)                  \
 {                                                                             \
-	return sprintf(buf,"%d\n",				              \
+	return sprintf(buf,"%d\n", (unsigned int)                             \
 		       ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA_##_define));          \
 }                                                                             \
                                                                               \
diff -Nru a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
--- a/drivers/s390/scsi/zfcp_sysfs_port.c	2004-08-07 11:05:36 -07:00
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c	2004-08-24 02:09:01 -07:00
@@ -26,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.41 $"
+#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.43 $"
 
 #include "zfcp_ext.h"
 
@@ -66,6 +66,8 @@
 ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
 ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
 ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id);
+ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
+		      (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
 
 /**
  * zfcp_sysfs_unit_add_store - add a unit to sysfs tree
@@ -107,7 +109,7 @@
 	zfcp_unit_put(unit);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
@@ -164,7 +166,7 @@
 	zfcp_unit_dequeue(unit);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
@@ -206,7 +208,7 @@
 	zfcp_erp_wait(port->adapter);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 /**
@@ -231,29 +233,6 @@
 
 static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_port_failed_show,
 		   zfcp_sysfs_port_failed_store);
-
-/**
- * zfcp_sysfs_port_in_recovery_show - recovery state of port
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- * 
- * Show function of "in_recovery" attribute of port. Will be
- * "0" if no error recovery is pending for port, otherwise "1".
- */
-static ssize_t
-zfcp_sysfs_port_in_recovery_show(struct device *dev, char *buf)
-{
-	struct zfcp_port *port;
-
-	port = dev_get_drvdata(dev);
-	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status))
-		return sprintf(buf, "1\n");
-	else
-		return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_port_in_recovery_show,
-		   NULL);
 
 /**
  * zfcp_port_common_attrs
diff -Nru a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c	2004-05-19 09:03:01 -07:00
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c	2004-08-24 02:09:01 -07:00
@@ -26,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.25 $"
+#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.27 $"
 
 #include "zfcp_ext.h"
 
@@ -64,6 +64,8 @@
 
 ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status));
 ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
+ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
+		      (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
 
 /**
  * zfcp_sysfs_unit_failed_store - failed state of unit
@@ -101,7 +103,7 @@
 	zfcp_erp_wait(unit->port->adapter);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 /**
@@ -126,29 +128,6 @@
 
 static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show,
 		   zfcp_sysfs_unit_failed_store);
-
-/**
- * zfcp_sysfs_unit_in_recovery_show - recovery state of unit
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- *
- * Show function of "in_recovery" attribute of unit. Will be
- * "0" if no error recovery is pending for unit, otherwise "1".
- */
-static ssize_t
-zfcp_sysfs_unit_in_recovery_show(struct device *dev, char *buf)
-{
-	struct zfcp_unit *unit;
-
-	unit = dev_get_drvdata(dev);
-	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status))
-		return sprintf(buf, "1\n");
-	else
-		return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_unit_in_recovery_show,
-		   NULL);
 
 static struct attribute *zfcp_unit_attrs[] = {
 	&dev_attr_scsi_lun.attr,
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	2004-07-26 15:15:55 -07:00
+++ b/drivers/scsi/Kconfig	2004-08-25 09:26:15 -07:00
@@ -320,7 +320,7 @@
 
 config SCSI_AIC7XXX_OLD
 	tristate "Adaptec AIC7xxx support (old driver)"
-	depends on SCSI
+	depends on (ISA || EISA || PCI ) && SCSI
 	help
 	  WARNING This driver is an older aic7xxx driver and is no longer
 	  under active development.  Adaptec, Inc. is writing a new driver to
@@ -395,15 +395,7 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called in2000.
 
-config SCSI_MEGARAID
-	tristate "AMI MegaRAID support"
-	depends on PCI && SCSI
-	help
-	  This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490
-	  and 467 SCSI host adapters.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called megaraid.
+source "drivers/scsi/megaraid/Kconfig.megaraid"
 
 config SCSI_SATA
 	bool "Serial ATA (SATA) support"
@@ -595,7 +587,7 @@
 
 config SCSI_EATA_PIO
 	tristate "EATA-PIO (old DPT PM2001, PM2012A) support"
-	depends on SCSI
+	depends on (ISA || EISA || PCI) && SCSI
 	---help---
 	  This driver supports all EATA-PIO protocol compliant SCSI Host
 	  Adapters like the DPT PM2001 and the PM2012A.  EATA-DMA compliant
@@ -780,6 +772,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ips.
 
+config SCSI_IBMVSCSI
+	tristate "IBM Virtual SCSI support"
+	depends on PPC_PSERIES || PPC_ISERIES
+	help
+	  This is the IBM POWER Virtual SCSI Client
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ibmvscsic.
+
 config SCSI_INITIO
 	tristate "Initio 9100U(W) support"
 	depends on PCI && SCSI && BROKEN
@@ -1462,7 +1463,7 @@
 
 config SCSI_MESH
 	tristate "MESH (Power Mac internal SCSI) support"
-	depends on PPC_PMAC && SCSI
+	depends on PPC32 && PPC_PMAC && SCSI
 	help
 	  Many Power Macintoshes and clones have a MESH (Macintosh Enhanced
 	  SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the
@@ -1507,7 +1508,7 @@
 
 config JAZZ_ESP
 	bool "MIPS JAZZ FAS216 SCSI support"
-	depends on MIPS_JAZZ && SCSI
+	depends on MACH_JAZZ && SCSI
 	help
 	  This is the driver for the onboard SCSI host adapter of MIPS Magnum
 	  4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile	2004-06-26 15:40:23 -07:00
+++ b/drivers/scsi/Makefile	2004-06-22 16:51:44 -07:00
@@ -95,7 +95,8 @@
 obj-$(CONFIG_SCSI_EATA)		+= eata.o
 obj-$(CONFIG_SCSI_DC395x)	+= dc395x.o
 obj-$(CONFIG_SCSI_DC390T)	+= tmscsim.o
-obj-$(CONFIG_SCSI_MEGARAID)	+= megaraid.o
+obj-$(CONFIG_MEGARAID_LEGACY)	+= megaraid.o
+obj-$(CONFIG_MEGARAID_NEWGEN)	+= megaraid/
 obj-$(CONFIG_SCSI_ACARD)	+= atp870u.o
 obj-$(CONFIG_SCSI_SUNESP)	+= esp.o
 obj-$(CONFIG_SCSI_GDTH)		+= gdth.o
@@ -119,6 +120,7 @@
 obj-$(CONFIG_SCSI_LASI700)	+= 53c700.o lasi700.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
 obj-$(CONFIG_SCSI_IPR)		+= ipr.o
+obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsi/
 obj-$(CONFIG_SCSI_SATA_SVW)	+= libata.o sata_svw.o
 obj-$(CONFIG_SCSI_ATA_PIIX)	+= libata.o ata_piix.o
 obj-$(CONFIG_SCSI_SATA_PROMISE)	+= libata.o sata_promise.o
diff -Nru a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
--- a/drivers/scsi/NCR5380.c	2004-07-26 14:21:24 -07:00
+++ b/drivers/scsi/NCR5380.c	2004-08-24 16:42:28 -07:00
@@ -310,12 +310,8 @@
  * possible) function may be used.  Before the specific driver initialization
  * code finishes, NCR5380_print_options should be called.
  */
-
 static int do_abort(struct Scsi_Host *host);
 static void do_reset(struct Scsi_Host *host);
-static struct NCR5380_hostdata *first_host = NULL;
-static struct NCR5380_hostdata *last_host = NULL;
-static struct timer_list usleep_timer;
 
 /*
  *	initialize_SCp		-	init the scsi pointer field
@@ -533,9 +529,6 @@
 #define USLEEP_WAITLONG USLEEP_SLEEP
 #endif
 
-static struct Scsi_Host *expires_first = NULL;
-static spinlock_t timer_lock;	/* Guards expires list */
-
 /* 
  * Function : int should_disconnect (unsigned char cmd)
  *
@@ -578,90 +571,10 @@
 	}
 }
 
-/*
- * Assumes instance->time_expires has been set in higher level code.
- * We should move to a timer per host
- *
- * Locks: Takes the timer queue lock
- */
-
-static int NCR5380_set_timer(struct Scsi_Host *instance)
+static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout)
 {
-	struct Scsi_Host *tmp, **prev;
-	unsigned long flags;
-
-	if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
-		return -1;
-	}
-	
-	spin_lock_irqsave(&timer_lock, flags);
-	for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
-		if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires)
-			break;
-
-	((struct NCR5380_hostdata *) instance->hostdata)->next_timer = tmp;
-	*prev = instance;
-
-	mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
-	
-	spin_unlock_irqrestore(&timer_lock, flags);
-	return 0;
-}
-
-/**
- *	NCR5380_timer_fn	-	handle polled timeouts
- *	@unused: unused
- *
- *	Walk the list of controllers, find which controllers have exceeded
- *	their expiry timeout and then schedule the processing co-routine to
- *	do the real work.
- *
- *	Doing something about unwanted reentrancy here might be useful 
- *
- *	Locks: disables irqs, takes and frees the timer lock
- */
- 
-static void NCR5380_timer_fn(unsigned long unused)
-{
-	struct Scsi_Host *instance;
-	struct NCR5380_hostdata *hostdata;
-	unsigned long flags;
-
-	spin_lock_irqsave(&timer_lock, flags);
-	for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) 
-	{
-		hostdata = (struct NCR5380_hostdata *) expires_first->hostdata;
-		schedule_work(&hostdata->coroutine);
-		instance = hostdata->next_timer;
-		hostdata->next_timer = NULL;
-		hostdata->time_expires = 0;
-		expires_first = instance;
-	}
-
-	del_timer(&usleep_timer);
-	if (expires_first) {
-		usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
-		add_timer(&usleep_timer);
-	}
-	spin_unlock_irqrestore(&timer_lock, flags);
-}
-
-/**
- *	NCR5380_all_init	-	global setup
- *
- *	Set up the global values and timers needed by the NCR5380 driver
- */
- 
-static inline void NCR5380_all_init(void)
-{
-	static int done = 0;
-	if (!done) {
-		dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
-		done = 1;
-		init_timer(&usleep_timer);
-		spin_lock_init(&timer_lock);
-		usleep_timer.function = NCR5380_timer_fn;
-	}
+	hostdata->time_expires = jiffies + timeout;
+	schedule_delayed_work(&hostdata->coroutine, hostdata->time_expires);
 }
 
 
@@ -788,22 +701,6 @@
 }
 
 /**
- *	NCR5380_coroutine_running	-	coroutine status
- *	@instance: controller to check
- *
- *	Return true if the co-routine for this controller is running
- *	or scheduled to run
- *
- *	FIXME: this test function belongs in the workqueue code!
- */
- 
-static int NCR5380_coroutine_running(struct Scsi_Host *instance)
-{
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
-	return test_bit(0, &hostdata->coroutine.pending);
-}
-
-/**
  *	NCR5380_print_status 	-	dump controller info
  *	@instance: controller to dump
  *
@@ -819,8 +716,6 @@
 	char *start;
 	int len;
 
-	printk("NCR5380 : coroutine is%s running.\n",  NCR5380_coroutine_running(instance)? "" : "n't");
-
 	NCR5380_dprint(NDEBUG_ANY, instance);
 	NCR5380_dprint_phase(NDEBUG_ANY, instance);
 
@@ -900,7 +795,6 @@
 	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n", pas_wmaxi, pas_maxi);
 #endif
 	spin_lock_irq(instance->host_lock);
-	SPRINTF("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance) ? "" : "n't");
 	if (!hostdata->connected)
 		SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
 	else
@@ -912,7 +806,6 @@
 	SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
 		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
-
 	spin_unlock_irq(instance->host_lock);
 	
 	*start = buffer;
@@ -964,7 +857,7 @@
  *	Locks: interrupts must be enabled when we are called 
  */
 
-static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
+static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags)
 {
 	NCR5380_local_declare();
 	int i, pass;
@@ -984,7 +877,6 @@
 #endif
 
 	NCR5380_setup(instance);
-	NCR5380_all_init();
 
 	hostdata->aborted = 0;
 	hostdata->id_mask = 1 << instance->this_id;
@@ -1021,18 +913,8 @@
 	else
 		hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;
 
-	hostdata->next = NULL;
-	
-	if (!first_host)
-		first_host = hostdata;
-	else
-		last_host->next = hostdata;
-
-	last_host = hostdata;
-	
 	hostdata->host = instance;
 	hostdata->time_expires = 0;
-	hostdata->next_timer = NULL;
 
 #ifndef AUTOSENSE
 	if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
@@ -1089,6 +971,19 @@
 }
 
 /**
+ *	NCR5380_exit	-	remove an NCR5380
+ *	@instance: adapter to remove
+ */
+
+static void __devexit NCR5380_exit(struct Scsi_Host *instance)
+{
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
+
+	cancel_delayed_work(&hostdata->coroutine);
+	flush_scheduled_work();
+}
+
+/**
  *	NCR5380_queue_command 		-	queue a command
  *	@cmd: SCSI command
  *	@done: completion handler
@@ -1169,6 +1064,7 @@
 	return 0;
 }
 
+
 /**
  *	NCR5380_main	-	NCR state machines
  *
@@ -1184,28 +1080,11 @@
 static void NCR5380_main(void *p)
 {
 	struct NCR5380_hostdata *hostdata = p;
+	struct Scsi_Host *instance = hostdata->host;
 	Scsi_Cmnd *tmp, *prev;
-	struct Scsi_Host *instance;
 	int done;
-	unsigned long flags = 0;
 	
-	/*
-	 * We run (with interrupts disabled) until we're sure that none of 
-	 * the host adapters have anything that can be done, at which point 
-	 * we can exit
-	 *
-	 * Interrupts are enabled before doing various other internal 
-	 * instructions, after we've decided that we need to run through
-	 * the loop again.
-	 *
-	 * this should prevent any race conditions.
-	 */
-
-	instance = hostdata->host;
-
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_lock_irqsave(instance->host_lock, flags);
-
+	spin_lock_irq(instance->host_lock);
 	do {
 		/* Lock held here */
 		done = 1;
@@ -1286,8 +1165,7 @@
 				LIST(tmp, hostdata->issue_queue);
 				tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
 				hostdata->issue_queue = tmp;
-				hostdata->time_expires = jiffies + USLEEP_WAITLONG;
-				NCR5380_set_timer(instance);
+				NCR5380_set_timer(hostdata, USLEEP_WAITLONG);
 			}
 		}	/* if hostdata->selecting */
 		if (hostdata->connected
@@ -1304,8 +1182,7 @@
 			break;
 	} while (!done);
 	
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_unlock_irqrestore(instance->host_lock, flags);
+	spin_unlock_irq(instance->host_lock);
 }
 
 #ifndef DONT_USE_INTR
@@ -1330,12 +1207,13 @@
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	int done;
 	unsigned char basr;
+	unsigned long flags;
 
 	dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
 
 	do {
 		done = 1;
-		spin_lock_irq(instance->host_lock);
+		spin_lock_irqsave(instance->host_lock, flags);
 		/* Look for pending interrupts */
 		NCR5380_setup(instance);
 		basr = NCR5380_read(BUS_AND_STATUS_REG);
@@ -1386,7 +1264,7 @@
 #endif
 			}
 		}	/* if BASR_IRQ */
-		spin_unlock_irq(instance->host_lock);
+		spin_unlock_irqrestore(instance->host_lock, flags);
 		if(!done)
 			schedule_work(&hostdata->coroutine);
 	} while (!done);
@@ -1469,12 +1347,8 @@
 	int err;
 	NCR5380_setup(instance);
 
-	if (hostdata->selecting) {
-		if(instance->irq != SCSI_IRQ_NONE)
-			spin_unlock_irq(instance->host_lock);
-		goto part2;	/* RvC: sorry prof. Dijkstra, but it keeps the
-				   rest of the code nearly the same */
-	}
+	if (hostdata->selecting)
+		goto part2;
 
 	hostdata->restart_select = 0;
 
@@ -1495,16 +1369,12 @@
 	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
 	NCR5380_write(MODE_REG, MR_ARBITRATE);
 
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_unlock_irq(instance->host_lock);
 
 	/* We can be relaxed here, interrupts are on, we are
 	   in workqueue context, the birds are singing in the trees */
-
+	spin_unlock_irq(instance->host_lock);
 	err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ);
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_lock_irq(instance->host_lock);
-
+	spin_lock_irq(instance->host_lock);
 	if (err < 0) {
 		printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__);
 		NCR5380_write(MODE_REG, MR_BASE);
@@ -1628,8 +1498,7 @@
 	if (!value && (hostdata->select_time < HZ/4)) {
 		/* RvC: we still must wait for a device response */
 		hostdata->select_time++;	/* after 25 ticks the device has failed */
-		hostdata->time_expires = jiffies + 1;
-		NCR5380_set_timer(instance);
+		NCR5380_set_timer(hostdata, 1);
 		return 0;	/* RvC: we return here with hostdata->selecting set,
 				   to go to sleep */
 	}
@@ -1638,8 +1507,6 @@
 					   waiting period */
 	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-		if(instance->irq != SCSI_IRQ_NONE)
-			spin_lock_irq(instance->host_lock);
 		NCR5380_reselect(instance);
 		printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
@@ -1665,8 +1532,6 @@
 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 			return -1;
 		}
-		if(instance->irq != SCSI_IRQ_NONE)
-			spin_lock_irq(instance->host_lock);
 		cmd->result = DID_BAD_TARGET << 16;
 		collect_stats(hostdata, cmd);
 		cmd->scsi_done(cmd);
@@ -1693,11 +1558,13 @@
 	 */
 
 	/* Wait for start of REQ/ACK handshake */
-	
+
+	spin_unlock_irq(instance->host_lock);
 	err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
+	spin_lock_irq(instance->host_lock);
 	
-	if(err)
-	{	printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
+	if(err) {
+		printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 		goto failed;
 	}
@@ -1705,9 +1572,6 @@
 	dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id));
 	tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun);
 
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_lock_irq(instance->host_lock);
-		
 	len = 1;
 	cmd->tag = 0;
 
@@ -1720,15 +1584,14 @@
 	hostdata->connected = cmd;
 	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
 
-	initialize_SCp(cmd);
-
+	if (cmd->SCp.ptr != (char *)cmd->sense_buffer) {
+		initialize_SCp(cmd);
+	}
 
 	return 0;
 
 	/* Selection failed */
 failed:
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_lock_irq(instance->host_lock);
 	return -1;
 
 }
@@ -1804,8 +1667,7 @@
 		while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);
 		if (!(tmp & SR_REQ)) {
 			/* timeout condition */
-			hostdata->time_expires = jiffies + USLEEP_SLEEP;
-			NCR5380_set_timer(instance);
+			NCR5380_set_timer(hostdata, USLEEP_SLEEP);
 			break;
 		}
 
@@ -2643,9 +2505,8 @@
 				 */
 				NCR5380_transfer_pio(instance, &phase, &len, &data);
 				if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) {
-					hostdata->time_expires = jiffies + USLEEP_SLEEP;
+					NCR5380_set_timer(hostdata, USLEEP_SLEEP);
 					dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
-					NCR5380_set_timer(instance);
 					return;
 				}
 				break;
@@ -2664,9 +2525,8 @@
 			/* RvC: go to sleep if polling time expired
 			 */
 			if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) {
-				hostdata->time_expires = jiffies + USLEEP_SLEEP;
+				NCR5380_set_timer(hostdata, USLEEP_SLEEP);
 				dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
-				NCR5380_set_timer(instance);
 				return;
 			}
 		}
diff -Nru a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
--- a/drivers/scsi/NCR5380.h	2003-08-21 01:36:23 -07:00
+++ b/drivers/scsi/NCR5380.h	2004-08-24 16:42:28 -07:00
@@ -251,7 +251,6 @@
 struct NCR5380_hostdata {
 	NCR5380_implementation_fields;		/* implementation specific */
 	struct Scsi_Host *host;			/* Host backpointer */
-	struct NCR5380_hostdata *next;		/* Next in our hot chain */
 	unsigned char id_mask, id_higher_mask;	/* 1 << id, all bits greater */
 	unsigned char targets_present;		/* targets we have connected
 						   to, so we can call a select
@@ -270,7 +269,6 @@
 	volatile unsigned aborted:1;		/* flag, says aborted */
 	int flags;
 	unsigned long time_expires;		/* in jiffies, set prior to sleeping */
-	struct Scsi_Host *next_timer;
 	int select_time;			/* timer in select for target response */
 	volatile Scsi_Cmnd *selecting;
 	struct work_struct coroutine;		/* our co-routine */
@@ -295,6 +293,7 @@
 static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
 #endif
 static int NCR5380_init(struct Scsi_Host *instance, int flags);
+static void NCR5380_exit(struct Scsi_Host *instance);
 static void NCR5380_information_transfer(struct Scsi_Host *instance);
 #ifndef DONT_USE_INTR
 static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
--- a/drivers/scsi/NCR53c406a.c	2004-05-12 08:46:22 -07:00
+++ b/drivers/scsi/NCR53c406a.c	2004-08-03 21:28:44 -07:00
@@ -606,22 +606,23 @@
 }
 
 /* called from init/main.c */
-static void __init NCR53c406a_setup(char *str, int *ints)
+static int __init NCR53c406a_setup(char *str)
 {
 	static size_t setup_idx = 0;
 	size_t i;
+	int ints[4];
 
 	DEB(printk("NCR53c406a: Setup called\n");
 	    );
 
 	if (setup_idx >= PORT_COUNT - 1) {
 		printk("NCR53c406a: Setup called too many times.  Bad LILO params?\n");
-		return;
+		return 0;
 	}
 	if (ints[0] < 1 || ints[0] > 3) {
 		printk("NCR53c406a: Malformed command line\n");
 		printk("NCR53c406a: Usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]]\n");
-		return;
+		return 0;
 	}
 	for (i = 0; i < PORT_COUNT && !port_base; i++)
 		if (ports[i] == ints[1]) {
@@ -631,7 +632,7 @@
 		}
 	if (!port_base) {
 		printk("NCR53c406a: Invalid PORTBASE 0x%x specified\n", ints[1]);
-		return;
+		return 0;
 	}
 
 	if (ints[0] > 1) {
@@ -654,6 +655,7 @@
 		fast_pio = ints[3];
 
 	DEB(printk("NCR53c406a: port_base=0x%x, irq=%d, fast_pio=%d\n", port_base, irq_level, fast_pio);)
+	return 1;
 }
 
 __setup("ncr53c406a=", NCR53c406a_setup);
diff -Nru a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
--- a/drivers/scsi/NCR_Q720.c	2004-06-20 07:18:41 -07:00
+++ b/drivers/scsi/NCR_Q720.c	2004-06-30 19:44:03 -07:00
@@ -216,7 +216,21 @@
 		goto out_free;
 	}
 	
-	mem_base = (__u32)ioremap(base_addr, mem_size);
+	if (dma_declare_coherent_memory(dev, base_addr, base_addr,
+					mem_size, DMA_MEMORY_MAP)
+	    != DMA_MEMORY_MAP) {
+		printk(KERN_ERR "NCR_Q720: DMA declare memory failed\n");
+		goto out_release_region;
+	}
+
+	/* The first 1k of the memory buffer is a memory map of the registers
+	 */
+	mem_base = (__u32)dma_mark_declared_memory_occupied(dev, base_addr,
+							    1024);
+	if (IS_ERR((void *)mem_base)) {
+		printk("NCR_Q720 failed to reserve memory mapped region\n");
+		goto out_release;
+	}
 
 	/* now also enable accesses in asr 2 */
 	asr2 = inb(io_base + 0x0a);
@@ -296,7 +310,8 @@
 	return 0;
 
  out_release:
-	iounmap((void *)mem_base);
+	dma_release_declared_memory(dev);
+ out_release_region:
 	release_mem_region(base_addr, mem_size);
  out_free:
 	kfree(p);
@@ -321,7 +336,7 @@
 		if(p->hosts[i])
 			NCR_Q720_remove_one(p->hosts[i]);
 
-	iounmap((void *)p->mem_base);
+	dma_release_declared_memory(dev);
 	release_mem_region(p->phys_mem_base, p->mem_size);
 	free_irq(p->irq, p);
 	kfree(p);
diff -Nru a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README
--- a/drivers/scsi/aacraid/README	2004-05-30 09:40:52 -07:00
+++ b/drivers/scsi/aacraid/README	2004-08-05 09:56:12 -07:00
@@ -10,14 +10,23 @@
 
 Supported Cards/Chipsets
 -------------------------
-	AAR-2410SA SATA
+	Adaptec 2020S
+	Adaptec 2025S
 	Adaptec 2120S
 	Adaptec 2200S
 	Adaptec 2230S
+	Adaptec 2240S
+	Adaptec 2410SA
+	Adaptec 2610SA
+	Adaptec 2810SA
+	Adaptec 21610SA
 	Adaptec 3230S
 	Adaptec 3240S
+	Adaptec 4000SAS
+	Adaptec 4005SAS
+	Adaptec 4800SAS
+	Adaptec 4805SAS
 	Adaptec 5400S
-	ASR-2020S PCI-X
 	Dell PERC 2 Quad Channel
 	Dell PERC 2/Si
 	Dell PERC 3/Si
@@ -49,7 +58,6 @@
 Mailing List
 -------------------------
 linux-scsi@vger.kernel.org (Interested parties troll here)
-http://mbserver.adaptec.com/ (Currently more Community Support than Devel Support)
 Also note this is very different to Brian's original driver
 so don't expect him to support it.
 Adaptec does support this driver.  Contact either tech support or Mark Salyzyn.
diff -Nru a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
--- a/drivers/scsi/aacraid/aachba.c	2004-07-12 01:00:54 -07:00
+++ b/drivers/scsi/aacraid/aachba.c	2004-08-10 09:26:16 -07:00
@@ -179,6 +179,20 @@
 static char *aac_get_status_string(u32 status);
 #endif
 
+/*
+ *	Non dasd selection is handled entirely in aachba now
+ */	
+ 
+MODULE_PARM(nondasd, "i");
+MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
+MODULE_PARM(dacmode, "i");
+MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
+MODULE_PARM(commit, "i");
+MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
+
+static int nondasd = -1;
+static int dacmode = -1;
+
 /**
  *	aac_get_containers	-	list containers
  *	@common: adapter to probe
@@ -481,8 +495,7 @@
 
 	dev->nondasd_support = 0;
 	if(dev->adapter_info.options & AAC_OPT_NONDASD){
-//		dev->nondasd_support = 1;
-// dmb - temporarily disable nondasd
+		dev->nondasd_support = 1;
 	}
 	if(nondasd != -1) {  
 		dev->nondasd_support = (nondasd!=0);
@@ -491,18 +504,30 @@
 		printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
 	}
 
-	dev->pae_support = 0;
+	dev->dac_support = 0;
 	if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){
 		printk(KERN_INFO "%s%d: 64bit support enabled.\n", dev->name, dev->id);
-		dev->pae_support = 1;
+		dev->dac_support = 1;
 	}
 
-	if(paemode != -1){
-		dev->pae_support = (paemode!=0);
+	if(dacmode != -1) {
+		dev->dac_support = (dacmode!=0);
 	}
-	if(dev->pae_support != 0) {
-		printk(KERN_INFO"%s%d: 64 Bit PAE enabled\n", dev->name, dev->id);
-		pci_set_dma_mask(dev->pdev, (dma_addr_t)0xFFFFFFFFFFFFFFFFULL);
+	if(dev->dac_support != 0) {
+		if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL) &&
+			!pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL)) {
+			printk(KERN_INFO"%s%d: 64 Bit DAC enabled\n",
+				dev->name, dev->id);
+		} else if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFULL) &&
+			!pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFULL)) {
+			printk(KERN_INFO"%s%d: DMA mask set failed, 64 Bit DAC disabled\n",
+				dev->name, dev->id);
+			dev->dac_support = 0;
+		} else {
+			printk(KERN_WARNING"%s%d: No suitable DMA available.\n",
+				dev->name, dev->id);
+			rcode = -ENOMEM;
+		}
 	}
 
 	fib_complete(fibptr);
@@ -537,7 +562,7 @@
 			scsicmd->use_sg,
 			scsicmd->sc_data_direction);
 	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr,
+		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
 				 scsicmd->request_bufflen,
 				 scsicmd->sc_data_direction);
 	readreply = (struct aac_read_reply *)fib_data(fibptr);
@@ -582,7 +607,7 @@
 			scsicmd->use_sg,
 			scsicmd->sc_data_direction);
 	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr,
+		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
 				 scsicmd->request_bufflen,
 				 scsicmd->sc_data_direction);
 
@@ -644,7 +669,7 @@
 
 	fib_init(cmd_fibcontext);
 
-	if(dev->pae_support == 1){
+	if(dev->dac_support == 1) {
 		struct aac_read64 *readcmd;
 		readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
 		readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -752,7 +777,7 @@
 	}
 	fib_init(cmd_fibcontext);
 
-	if(dev->pae_support == 1){
+	if(dev->dac_support == 1) {
 		struct aac_write64 *writecmd;
 		writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
 		writecmd->command = cpu_to_le32(VM_CtHostWrite64);
@@ -1220,7 +1245,7 @@
 			scsicmd->use_sg,
 			scsicmd->sc_data_direction);
 	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen,
+		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen,
 			scsicmd->sc_data_direction);
 
 	/*
@@ -1348,7 +1373,12 @@
 	case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
 	default:
 #ifdef AAC_DETAILED_STATUS_INFO
-		printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",le32_to_cpu(srbreply->srb_status&0x3f),aac_get_status_string(le32_to_cpu(srbreply->srb_status)), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status) );
+		printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
+			le32_to_cpu(srbreply->srb_status & 0x3F),
+			aac_get_status_string(
+				le32_to_cpu(srbreply->srb_status) & 0x3F), 
+			scsicmd->cmnd[0], 
+			le32_to_cpu(srbreply->scsi_status));
 #endif
 		scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
 		break;
@@ -1358,7 +1388,10 @@
 		scsicmd->result |= SAM_STAT_CHECK_CONDITION;
 		len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
 				sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
-		dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len));
+#ifdef AAC_DETAILED_STATUS_INFO
+		dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", 
+					le32_to_cpu(srbreply->status), len));
+#endif
 		memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
 		
 	}
@@ -1437,7 +1470,7 @@
 	srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
 	srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);
 	
-	if( dev->pae_support ==1 ) {
+	if( dev->dac_support == 1 ) {
 		aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg);
 		srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
 
@@ -1532,7 +1565,7 @@
 		psg->count = cpu_to_le32(1);
 		psg->sg[0].addr = cpu_to_le32(addr);
 		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-		scsicmd->SCp.ptr = (char *)(ulong)addr;
+		scsicmd->SCp.dma_handle = addr;
 		byte_count = scsicmd->request_bufflen;
 	}
 	return byte_count;
@@ -1593,7 +1626,7 @@
 		psg->sg[0].addr[1] = (u32)(le_addr>>32);
 		psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);
 		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-		scsicmd->SCp.ptr = (char *)(ulong)addr;
+		scsicmd->SCp.dma_handle = addr;
 		byte_count = scsicmd->request_bufflen;
 	}
 	return byte_count;
diff -Nru a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
--- a/drivers/scsi/aacraid/aacraid.h	2004-07-26 14:39:04 -07:00
+++ b/drivers/scsi/aacraid/aacraid.h	2004-08-15 22:49:55 -07:00
@@ -28,10 +28,7 @@
 #define aac_phys_to_logical(x)  (x+1)
 #define aac_logical_to_phys(x)  (x?x-1:0)
 
-#define AAC_DETAILED_STATUS_INFO
-
-extern int nondasd;
-extern int paemode;
+/* #define AAC_DETAILED_STATUS_INFO */
 
 struct diskparm
 {
@@ -404,15 +401,15 @@
 };
 
 enum aac_log_level {
-	LOG_INIT			= 10,
-	LOG_INFORMATIONAL		= 20,
-	LOG_WARNING			= 30,
-	LOG_LOW_ERROR			= 40,
-	LOG_MEDIUM_ERROR		= 50,
-	LOG_HIGH_ERROR			= 60,
-	LOG_PANIC			= 70,
-	LOG_DEBUG			= 80,
-	LOG_WINDBG_PRINT		= 90
+	LOG_AAC_INIT			= 10,
+	LOG_AAC_INFORMATIONAL		= 20,
+	LOG_AAC_WARNING			= 30,
+	LOG_AAC_LOW_ERROR		= 40,
+	LOG_AAC_MEDIUM_ERROR		= 50,
+	LOG_AAC_HIGH_ERROR		= 60,
+	LOG_AAC_PANIC			= 70,
+	LOG_AAC_DEBUG			= 80,
+	LOG_AAC_WINDBG_PRINT		= 90
 };
 
 #define FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT	0x030b
@@ -841,7 +838,7 @@
 	 * lets break them out so we don't have to do an AND to check them
 	 */
 	u8			nondasd_support; 
-	u8			pae_support;
+	u8			dac_support;
 };
 
 #define AllocateAndMapFibSpace(dev, MapFibContext) \
diff -Nru a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
--- a/drivers/scsi/aacraid/commctrl.c	2004-07-12 01:00:54 -07:00
+++ b/drivers/scsi/aacraid/commctrl.c	2004-08-09 15:07:39 -07:00
@@ -480,7 +480,7 @@
 	default:
 		data_dir = DMA_NONE;
 	}
-	if (dev->pae_support == 1) {
+	if (dev->dac_support == 1) {
 		struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
 		byte_count = 0;
 
diff -Nru a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
--- a/drivers/scsi/aacraid/commsup.c	2004-05-10 13:16:08 -07:00
+++ b/drivers/scsi/aacraid/commsup.c	2004-08-15 22:49:55 -07:00
@@ -761,7 +761,7 @@
 		length = 255;
 	if (cp[length] != 0)
 		cp[length] = 0;
-	if (level == LOG_HIGH_ERROR)
+	if (level == LOG_AAC_HIGH_ERROR)
 		printk(KERN_WARNING "aacraid:%s", cp);
 	else
 		printk(KERN_INFO "aacraid:%s", cp);
diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
--- a/drivers/scsi/aacraid/linit.c	2004-07-13 18:33:33 -07:00
+++ b/drivers/scsi/aacraid/linit.c	2004-08-18 20:54:47 -07:00
@@ -44,6 +44,7 @@
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/ioctl32.h>
+#include <linux/delay.h>
 #include <asm/semaphore.h>
 
 #include <scsi/scsi.h>
@@ -62,15 +63,7 @@
 		   "Adaptec Advanced Raid Products, "
 		   "and HP NetRAID-4M SCSI driver");
 MODULE_LICENSE("GPL");
-
-
-int nondasd = -1;
-module_param(nondasd, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
-
-int paemode = -1;
-module_param(paemode, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(paemode, "Control whether dma addressing is using PAE. 0=off, 1=on");
+MODULE_VERSION(AAC_DRIVER_VERSION);
 
 struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS];
 static unsigned aac_count;
@@ -83,44 +76,54 @@
  * Note: The last field is used to index into aac_drivers below.
  */
 static struct pci_device_id aac_pci_tbl[] = {
-	{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si */
-	{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di */
-	{ 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si */
-	{ 0x1028, 0x0004, 0x1028, 0x00d0, 0, 0, 3 }, /* PERC 3/Si */
-	{ 0x1028, 0x0002, 0x1028, 0x00d1, 0, 0, 4 }, /* PERC 3/Di */
-	{ 0x1028, 0x0002, 0x1028, 0x00d9, 0, 0, 5 }, /* PERC 3/Di */
-	{ 0x1028, 0x000a, 0x1028, 0x0106, 0, 0, 6 }, /* PERC 3/Di */
-	{ 0x1028, 0x000a, 0x1028, 0x011b, 0, 0, 7 }, /* PERC 3/Di */
-	{ 0x1028, 0x000a, 0x1028, 0x0121, 0, 0, 8 }, /* PERC 3/Di */
-	{ 0x9005, 0x0283, 0x9005, 0x0283, 0, 0, 9 }, /* catapult*/
-	{ 0x9005, 0x0284, 0x9005, 0x0284, 0, 0, 10 }, /* tomcat*/
-	{ 0x9005, 0x0285, 0x9005, 0x0286, 0, 0, 11 }, /* Adaptec 2120S (Crusader)*/
-	{ 0x9005, 0x0285, 0x9005, 0x0285, 0, 0, 12 }, /* Adaptec 2200S (Vulcan)*/
-	{ 0x9005, 0x0285, 0x9005, 0x0287, 0, 0, 13 }, /* Adaptec 2200S (Vulcan-2m)*/
-	{ 0x9005, 0x0285, 0x17aa, 0x0286, 0, 0, 14 }, /* Legend S220*/
-	{ 0x9005, 0x0285, 0x17aa, 0x0287, 0, 0, 15 }, /* Legend S230*/
-
-	{ 0x9005, 0x0285, 0x9005, 0x0288, 0, 0, 16 }, /* Adaptec 3230S (Harrier)*/
-	{ 0x9005, 0x0285, 0x9005, 0x0289, 0, 0, 17 }, /* Adaptec 3240S (Tornado)*/
-	{ 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020 ZCR PCI-X U320 */
-	{ 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2025 ZCR DIMM U320 */
-	{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 20 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/
-
-	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 21 }, /* Perc 320/DC*/
-	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 22 }, /* Adaptec 5400S (Mustang)*/
-	{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 23 }, /* Adaptec 5400S (Mustang)*/
-	{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 24 }, /* Dell PERC2 "Quad Channel" */
-	{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 25 }, /* HP NetRAID-4M */
-
+	{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */
+	{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */
+	{ 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */
+	{ 0x1028, 0x0004, 0x1028, 0x00d0, 0, 0, 3 }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */
+	{ 0x1028, 0x0002, 0x1028, 0x00d1, 0, 0, 4 }, /* PERC 3/Di (Viper/PERC3DiV) */
+	{ 0x1028, 0x0002, 0x1028, 0x00d9, 0, 0, 5 }, /* PERC 3/Di (Lexus/PERC3DiL) */
+	{ 0x1028, 0x000a, 0x1028, 0x0106, 0, 0, 6 }, /* PERC 3/Di (Jaguar/PERC3DiJ) */
+	{ 0x1028, 0x000a, 0x1028, 0x011b, 0, 0, 7 }, /* PERC 3/Di (Dagger/PERC3DiD) */
+	{ 0x1028, 0x000a, 0x1028, 0x0121, 0, 0, 8 }, /* PERC 3/Di (Boxster/PERC3DiB) */
+	{ 0x9005, 0x0283, 0x9005, 0x0283, 0, 0, 9 }, /* catapult */
+	{ 0x9005, 0x0284, 0x9005, 0x0284, 0, 0, 10 }, /* tomcat */
+	{ 0x9005, 0x0285, 0x9005, 0x0286, 0, 0, 11 }, /* Adaptec 2120S (Crusader) */
+	{ 0x9005, 0x0285, 0x9005, 0x0285, 0, 0, 12 }, /* Adaptec 2200S (Vulcan) */
+	{ 0x9005, 0x0285, 0x9005, 0x0287, 0, 0, 13 }, /* Adaptec 2200S (Vulcan-2m) */
+	{ 0x9005, 0x0285, 0x17aa, 0x0286, 0, 0, 14 }, /* Legend S220 (Legend Crusader) */
+	{ 0x9005, 0x0285, 0x17aa, 0x0287, 0, 0, 15 }, /* Legend S230 (Legend Vulcan) */
+
+	{ 0x9005, 0x0285, 0x9005, 0x0288, 0, 0, 16 }, /* Adaptec 3230S (Harrier) */
+	{ 0x9005, 0x0285, 0x9005, 0x0289, 0, 0, 17 }, /* Adaptec 3240S (Tornado) */
+	{ 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020ZCR SCSI PCI-X ZCR (Skyhawk) */
+	{ 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2025ZCR SCSI SO-DIMM PCI-X ZCR (Terminator) */
+	{ 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 20 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
+	{ 0x9005, 0x0286, 0x9005, 0x028d, 0, 0, 21 }, /* ASR-2130S (Lancer) */
+	{ 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 22 }, /* Jupiter Platform */
+	{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 23 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
+	{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 24 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
+	{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 25 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
 	{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 26 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
 	{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 27 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
 	{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 28 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
 	{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 29 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
-	{ 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* SATA 6Ch (Bearcat) */
-
-	{ 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 31 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
-	{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 32 }, /* ASR-2020SA      (ZCR PCI-X SATA) */
-	{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 33 }, /* ASR-2025SA      (ZCR DIMM SATA) */
+	{ 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* AAR-2610SA PCI SATA 6ch */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 31 }, /* ASR-2240S */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 32 }, /* ASR-4005SAS */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 33 }, /* ASR-4000SAS */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 34 }, /* ASR-4800SAS */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 35 }, /* ASR-4805SAS */
+
+	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 36 }, /* Perc 320/DC*/
+	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 37 }, /* Adaptec 5400S (Mustang)*/
+	{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 38 }, /* Adaptec 5400S (Mustang)*/
+	{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 39 }, /* Dell PERC2/QC */
+	{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 40 }, /* HP NetRAID-4M */
+
+	{ 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 41 }, /* Dell Catchall */
+	{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 42 }, /* Legend Catchall */
+	{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 43 }, /* Adaptec Catch All */
+	{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 44 }, /* Adaptec Rocket Catch All */
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -131,44 +134,54 @@
  * for the card.  At that time we can remove the channels from here
  */
 static struct aac_driver_ident aac_drivers[] = {
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 2/Si */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "catapult        ", 2, AAC_QUIRK_31BIT }, /* catapult*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "tomcat          ", 2, AAC_QUIRK_31BIT }, /* tomcat*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2120S   ", 1, AAC_QUIRK_31BIT }, /* Adaptec 2120S (Crusader)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan-2m)*/
-	{ aac_rx_init, "aacraid",  "Legend  ", "Legend S220     ", 1, AAC_QUIRK_31BIT }, /* Legend S220*/
-	{ aac_rx_init, "aacraid",  "Legend  ", "Legend S230     ", 2, AAC_QUIRK_31BIT }, /* Legend S230*/
-
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 3230S   ", 2 }, /* Adaptec 3230S (Harrier)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 3240S   ", 2 }, /* Adaptec 3240S (Tornado)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020ZCR     ", 2 }, /* ASR-2020 ZCR PCI-X U320 */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025ZCR     ", 2 }, /* ASR-2025 ZCR DIMM U320 */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/
-
-	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/
-	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4 }, /* Adaptec 5400S (Mustang)*/
-	{ aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4 }, /* Adaptec 5400S (Mustang)*/
-	{ aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2 "Quad Channel" */
-	{ aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4 },  /* HP NetRAID-4M */
-
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 2/Si (Iguana/PERC2Si) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Opal/PERC3Di) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si (SlimFast/PERC3Si */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Viper/PERC3DiV) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Lexus/PERC3DiL) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 1, AAC_QUIRK_31BIT }, /* PERC 3/Di (Jaguar/PERC3DiJ) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Dagger/PERC3DiD) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Boxster/PERC3DiB) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "catapult        ", 2, AAC_QUIRK_31BIT }, /* catapult */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "tomcat          ", 2, AAC_QUIRK_31BIT }, /* tomcat */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2120S   ", 1, AAC_QUIRK_31BIT }, /* Adaptec 2120S (Crusader) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan-2m) */
+	{ aac_rx_init, "aacraid",  "Legend  ", "Legend S220     ", 1, AAC_QUIRK_31BIT }, /* Legend S220 (Legend Crusader) */
+	{ aac_rx_init, "aacraid",  "Legend  ", "Legend S230     ", 2, AAC_QUIRK_31BIT }, /* Legend S230 (Legend Vulcan) */
+
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 3230S   ", 2 }, /* Adaptec 3230S (Harrier) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 3240S   ", 2 }, /* Adaptec 3240S (Tornado) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020ZCR     ", 2 }, /* ASR-2020ZCR SCSI PCI-X ZCR (Skyhawk) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025ZCR     ", 2 }, /* ASR-2025ZCR SCSI SO-DIMM PCI-X ZCR (Terminator) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-2130S PCI-X ", 1 }, /* ASR-2130S (Lancer) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "Callisto        ", 2 }, /* Jupiter Platform */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020SA       ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025SA       ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
 	{ aac_rx_init, "aacraid",  "DELL    ", "CERC SR2        ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "SO-DIMM SATA ZCR", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "SATA 6Channel   ", 1 }, /* SATA 6Ch (Bearcat) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2610SA      ", 1 }, /* SATA 6Ch (Bearcat) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2240S       ", 1 }, /* ASR-2240S */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4005SAS     ", 1 }, /* ASR-4005SAS */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4000SAS     ", 1 }, /* ASR-4000SAS */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4800SAS     ", 1 }, /* ASR-4800SAS */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4805SAS     ", 1 }, /* ASR-4805SAS */
 
-	{ aac_rkt_init,"aacraid",  "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020SA      ", 1 }, /* ASR-2020SA      (ZCR PCI-X SATA) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025SA      ", 1 }, /* ASR-2025SA      (ZCR DIMM SATA) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/
+	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4 }, /* Adaptec 5400S (Mustang)*/
+	{ aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4 }, /* Adaptec 5400S (Mustang)*/
+	{ aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2/QC */
+	{ aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4 }, /* HP NetRAID-4M */
+
+	{ aac_rx_init, "aacraid",  "DELL    ", "RAID            ", 2, AAC_QUIRK_31BIT }, /* Dell Catchall */
+	{ aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT }, /* Legend Catchall */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_31BIT }, /* Adaptec Catch All */
+	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec Rocket Catch All */
 };
 
 #ifdef CONFIG_COMPAT
@@ -408,15 +421,17 @@
 				}
 			}
 			spin_unlock_irqrestore(&dev->list_lock, flags);
+			if (active)
+				break;
 
-			/*
-			 * We can exit If all the commands are complete
-			 */
-			if (active == 0)
-				return SUCCESS;
 		}
+		/*
+		 * We can exit If all the commands are complete
+		 */
+		if (active == 0)
+			return SUCCESS;
 		spin_unlock_irq(host->host_lock);
-		scsi_sleep(HZ);
+		ssleep(1);
 		spin_lock_irq(host->host_lock);
 	}
 	printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
--- a/drivers/scsi/advansys.c	2004-06-26 08:49:45 -07:00
+++ b/drivers/scsi/advansys.c	2004-07-10 17:52:16 -07:00
@@ -15,16 +15,6 @@
  * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
  * changed its name to ConnectCom Solutions, Inc.
  *
- * There is an AdvanSys Linux WWW page at:
- *  http://www.connectcom.net/downloads/software/os/linux.html
- *  http://www.advansys.com/linux.html
- *
- * The latest released version of the AdvanSys driver is available at:
- *  ftp://ftp.advansys.com/pub/linux/linux.tgz
- *  ftp://ftp.connectcom.net/pub/linux/linux.tgz
- *
- * Please send questions, comments, bug reports to:
- *  support@connectcom.net
  */
 
 /*
@@ -41,7 +31,6 @@
   H. Release History
   I. Known Problems/Fix List
   J. Credits (Chronological Order)
-  K. ConnectCom (AdvanSys) Contact Information
 
   A. Linux Kernels Supported by this Driver
 
@@ -2032,9 +2021,6 @@
 #define ADV_LIB_VERSION_MAJOR  5
 #define ADV_LIB_VERSION_MINOR  14
 
-/* d_os_dep.h */
-#define ADV_OS_LINUX
-
 /*
  * Define Adv Library required special types.
  */
@@ -3370,9 +3356,9 @@
 /*
  * Default EEPROM Configuration structure defined in a_init.c.
  */
-extern ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
-extern ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
-extern ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
+static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
+static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
+static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
 
 /*
  * DvcGetPhyAddr() flag arguments
diff -Nru a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h
--- a/drivers/scsi/advansys.h	2004-06-26 08:49:45 -07:00
+++ b/drivers/scsi/advansys.h	2004-05-22 05:47:56 -07:00
@@ -13,36 +13,10 @@
  * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
  * changed its name to ConnectCom Solutions, Inc.
  *
- * There is an AdvanSys Linux WWW page at:
- *  http://www.connectcom.net/downloads/software/os/linux.html
- *  http://www.advansys.com/linux.html
- *
- * The latest released version of the AdvanSys driver is available at:
- *  ftp://ftp.advansys.com/pub/linux/linux.tgz
- *  ftp://ftp.connectcom.net/pub/linux/linux.tgz
- *
- * Please send questions, comments, bug reports to:
- *  linux@connectcom.net or bfrey@turbolinux.com.cn
  */
 
 #ifndef _ADVANSYS_H
 #define _ADVANSYS_H
-
-#include <linux/config.h>
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif /* LINUX_VERSION_CODE */
-
-/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */
-#define ASC_LINUX_VERSION(V, P, S)    (((V) * 65536) + ((P) * 256) + (S))
-/* Driver supported only in version 2.2 and version >= 2.4. */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,2,0) || \
-    (LINUX_VERSION_CODE > ASC_LINUX_VERSION(2,3,0) && \
-     LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0))
-#error "AdvanSys driver supported only in 2.2 and 2.4 or greater kernels."
-#endif
-#define ASC_LINUX_KERNEL22 (LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0))
-#define ASC_LINUX_KERNEL24 (LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,4,0))
 
 /*
  * Scsi_Host_Template function prototypes.
diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
--- a/drivers/scsi/aha1542.c	2004-07-26 14:21:48 -07:00
+++ b/drivers/scsi/aha1542.c	2004-08-18 19:38:11 -07:00
@@ -1479,7 +1479,7 @@
 	 * we are pretty desperate anyways.
 	 */
 	spin_unlock_irq(SCpnt->device->host->host_lock);
-	scsi_sleep(4 * HZ);
+	ssleep(4);
 	spin_lock_irq(SCpnt->device->host->host_lock);
 
 	WAIT(STATUS(SCpnt->device->host->io_port),
@@ -1543,7 +1543,7 @@
 	 * we are pretty desperate anyways.
 	 */
 	spin_unlock_irq(SCpnt->device->host->host_lock);
-	scsi_sleep(4 * HZ);
+	ssleep(4);
 	spin_lock_irq(SCpnt->device->host->host_lock);
 
 	WAIT(STATUS(SCpnt->device->host->io_port),
diff -Nru a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h
--- a/drivers/scsi/aha1542.h	2003-09-01 17:20:32 -07:00
+++ b/drivers/scsi/aha1542.h	2004-08-25 18:50:50 -07:00
@@ -91,10 +91,12 @@
 };
 
 /* These belong in scsi.h also */
-#define any2scsi(up, p)				\
-(up)[0] = (((unsigned long)(p)) >> 16)  ;	\
-(up)[1] = (((unsigned long)(p)) >> 8);		\
-(up)[2] = ((unsigned long)(p));
+static inline void any2scsi(u8 *p, u32 v)
+{
+	p[0] = v >> 16;
+	p[1] = v >> 8;
+	p[2] = v;
+}
 
 #define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
 
diff -Nru a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx	2004-03-09 07:18:34 -08:00
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx	2004-08-01 08:04:32 -07:00
@@ -46,7 +46,7 @@
 
 config AIC79XX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
-	depends on SCSI_AIC79XX
+	depends on SCSI_AIC79XX && !PREVENT_FIRMWARE_BUILD
 	help
 	This option should only be enabled if you are modifying the firmware
 	source to the aic79xx driver and wish to have the generated firmware
diff -Nru a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx	2004-03-09 07:18:34 -08:00
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx	2004-08-01 08:04:40 -07:00
@@ -61,7 +61,7 @@
 
 config AIC7XXX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
-	depends on SCSI_AIC7XXX
+	depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD
 	help
 	This option should only be enabled if you are modifying the firmware
 	source to the aic7xxx driver and wish to have the generated firmware
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-08-23 01:15:08 -07:00
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-08-24 16:09:04 -07:00
@@ -61,6 +61,7 @@
 #endif
 
 #include <linux/mm.h>		/* For fetching system memory size */
+#include <linux/delay.h>	/* For ssleep/msleep */
 
 /*
  * Lock protecting manipulation of the ahd softc list.
@@ -415,7 +416,6 @@
 /*
  * Module information and settable options.
  */
-#ifdef MODULE
 static char *aic79xx = NULL;
 /*
  * Just in case someone uses commas to separate items on the insmod
@@ -426,9 +426,8 @@
 
 MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
 MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
-#endif
+MODULE_VERSION(AIC79XX_DRIVER_VERSION);
 MODULE_PARM(aic79xx, "s");
 MODULE_PARM_DESC(aic79xx,
 "period delimited, options string.\n"
@@ -463,7 +462,6 @@
 "		Change Read Streaming for Controller's 2 and 3\n"
 "\n"
 "	options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
-#endif
 
 static void ahd_linux_handle_scsi_status(struct ahd_softc *,
 					 struct ahd_linux_device *,
@@ -3173,7 +3171,7 @@
 				break;
 			}
 			if (status & SSQ_DELAY)
-				scsi_sleep(1 * HZ);
+				ssleep(1);
 
 			break;
 		case SS_START:
@@ -3333,7 +3331,7 @@
 			}
 			if (targ->dv_state_retry <= 10) {
 				if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
-					scsi_sleep(ahd->our_id*HZ/10);
+					msleep(ahd->our_id*1000/10);
 				break;
 			}
 #ifdef AHD_DEBUG
@@ -3377,7 +3375,7 @@
 				targ->dv_state_retry--;
 			} else if (targ->dv_state_retry < 60) {
 				if ((status & SSQ_DELAY) != 0)
-					scsi_sleep(1 * HZ);
+					ssleep(1);
 			} else {
 #ifdef AHD_DEBUG
 				if (ahd_debug & AHD_SHOW_DV) {
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c	2003-12-30 10:12:35 -08:00
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c	2004-07-26 14:54:35 -07:00
@@ -452,8 +452,10 @@
 	 * or read prefetching could be initiated by the
 	 * CPU or host bridge.  Our device does not support
 	 * either, so look for data corruption and/or flaged
-	 * PCI errors.
+	 * PCI errors.  First pause without causing another
+	 * chip reset.
 	 */
+	hcntrl &= ~CHIPRST;
 	ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
 	while (ahd_is_paused(ahd) == 0)
 		;
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-06-25 07:50:05 -07:00
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-08-18 19:37:31 -07:00
@@ -140,6 +140,7 @@
 
 #include <linux/mm.h>		/* For fetching system memory size */
 #include <linux/blkdev.h>		/* For block_size() */
+#include <linux/delay.h>	/* For ssleep/msleep */
 
 /*
  * Lock protecting manipulation of the ahc softc list.
@@ -436,7 +437,6 @@
 /*
  * Module information and settable options.
  */
-#ifdef MODULE
 static char *aic7xxx = NULL;
 /*
  * Just in case someone uses commas to separate items on the insmod
@@ -447,9 +447,8 @@
 
 MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
 MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
-#endif
+MODULE_VERSION(AIC7XXX_DRIVER_VERSION);
 MODULE_PARM(aic7xxx, "s");
 MODULE_PARM_DESC(aic7xxx,
 "period delimited, options string.\n"
@@ -479,7 +478,6 @@
 "\n"
 "	options aic7xxx 'aic7xxx=probe_eisa_vl.tag_info:{{}.{.10}}.seltime:1'\n"
 );
-#endif
 
 static void ahc_linux_handle_scsi_status(struct ahc_softc *,
 					 struct ahc_linux_device *,
@@ -2825,7 +2823,7 @@
 				break;
 			}
 			if (status & SSQ_DELAY)
-				scsi_sleep(1 * HZ);
+				ssleep(1);
 
 			break;
 		case SS_START:
@@ -2985,7 +2983,7 @@
 			}
 			if (targ->dv_state_retry <= 10) {
 				if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
-					scsi_sleep(ahc->our_id*HZ/10);
+					msleep(ahc->our_id*1000/10);
 				break;
 			}
 #ifdef AHC_DEBUG
@@ -3029,7 +3027,7 @@
 				targ->dv_state_retry--;
 			} else if (targ->dv_state_retry < 60) {
 				if ((status & SSQ_DELAY) != 0)
-					scsi_sleep(1 * HZ);
+					ssleep(1);
 			} else {
 #ifdef AHC_DEBUG
 				if (ahc_debug & AHC_SHOW_DV) {
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c	2003-12-30 10:12:37 -08:00
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c	2004-07-26 14:54:35 -07:00
@@ -1284,8 +1284,10 @@
 	 * or read prefetching could be initiated by the
 	 * CPU or host bridge.  Our device does not support
 	 * either, so look for data corruption and/or flagged
-	 * PCI errors.
+	 * PCI errors.  First pause without causing another
+	 * chip reset.
 	 */
+	hcntrl &= ~CHIPRST;
 	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
 	while (ahc_is_paused(ahc) == 0)
 		;
diff -Nru a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
--- a/drivers/scsi/aic7xxx/aicasm/Makefile	2004-01-24 07:02:19 -08:00
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile	2004-07-26 16:48:36 -07:00
@@ -34,10 +34,14 @@
 	$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
 
 aicdb.h:
-	@if [ -e "/usr/include/db3/db_185.h" ]; then		\
+	@if [ -e "/usr/include/db4/db_185.h" ]; then		\
+		echo "#include <db4/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db3/db_185.h" ]; then		\
 		echo "#include <db3/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db2/db_185.h" ]; then		\
 		echo "#include <db2/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db1/db_185.h" ]; then		\
+		echo "#include <db1/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db/db_185.h" ]; then		\
 		echo "#include <db/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db_185.h" ]; then		\
diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
--- a/drivers/scsi/aic7xxx_old.c	2004-07-26 14:38:41 -07:00
+++ b/drivers/scsi/aic7xxx_old.c	2004-08-18 19:38:37 -07:00
@@ -10489,7 +10489,7 @@
       aic_outb(p, lastphase | ATNO, SCSISIGO);
       unpause_sequencer(p, FALSE);
       spin_unlock_irq(p->host->host_lock);
-      scsi_sleep(HZ);
+      ssleep(1);
       spin_lock_irq(p->host->host_lock);
       if(aic_dev->flags & BUS_DEVICE_RESET_PENDING)
         return FAILED;
@@ -10548,7 +10548,7 @@
   aic_outb(p, saved_scbptr, SCBPTR);
   unpause_sequencer(p, FALSE);
   spin_unlock_irq(p->host->host_lock);
-  scsi_sleep(HZ/4);
+  msleep(1000/4);
   spin_lock_irq(p->host->host_lock);
   if(aic_dev->flags & BUS_DEVICE_RESET_PENDING)
     return FAILED;
@@ -10786,7 +10786,7 @@
   }
   unpause_sequencer(p, FALSE);
   spin_unlock_irq(p->host->host_lock);
-  scsi_sleep(HZ/4);
+  msleep(1000/4);
   spin_lock_irq(p->host->host_lock);
   if (p->flags & AHC_ABORT_PENDING)
   {
@@ -10887,7 +10887,7 @@
   aic7xxx_run_done_queue(p, TRUE);
   unpause_sequencer(p, FALSE);
   spin_unlock_irq(p->host->host_lock);
-  scsi_sleep(2 * HZ);
+  ssleep(2);
   spin_lock_irq(p->host->host_lock);
   return SUCCESS;
 }
@@ -11139,6 +11139,7 @@
 #include "aic7xxx_old/aic7xxx_proc.c"
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(AIC7XXX_H_VERSION);
 
 
 static Scsi_Host_Template driver_template = {
diff -Nru a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
--- a/drivers/scsi/arm/cumana_1.c	2004-06-19 08:53:23 -07:00
+++ b/drivers/scsi/arm/cumana_1.c	2004-08-24 16:42:28 -07:00
@@ -321,6 +321,7 @@
 
 	scsi_remove_host(host);
 	free_irq(host->irq, host);
+	NCR5380_exit(host);
 	release_region(host->io_port, host->n_io_port);
 	scsi_host_put(host);
 }
diff -Nru a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c
--- a/drivers/scsi/arm/ecoscsi.c	2004-06-19 08:53:25 -07:00
+++ b/drivers/scsi/arm/ecoscsi.c	2004-08-24 16:42:28 -07:00
@@ -222,6 +222,7 @@
 
 	if (shpnt->irq != IRQ_NONE)
 		free_irq(shpnt->irq, NULL);
+	NCR5380_exit(host);
 	if (shpnt->io_port)
 		release_region(shpnt->io_port, shpnt->n_io_port);
 
diff -Nru a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
--- a/drivers/scsi/arm/eesox.c	2004-06-19 08:53:26 -07:00
+++ b/drivers/scsi/arm/eesox.c	2004-08-27 13:04:55 -07:00
@@ -231,7 +231,8 @@
 		 * Align buffer.
 		 */
 		if (((u32)buf) & 2 && status >= 2) {
-			*((u16 *)buf)++ = readl(reg_dmadata);
+			*(u16 *)buf = readl(reg_dmadata);
+			buf += 2;
 			status -= 2;
 			length -= 2;
 		}
@@ -243,8 +244,10 @@
 			l1 |= readl(reg_dmadata) << 16;
 			l2 = readl(reg_dmadata) & mask;
 			l2 |= readl(reg_dmadata) << 16;
-			*((u32 *)buf)++ = l1;
-			*((u32 *)buf)++ = l2;
+			*(u32 *)buf = l1;
+			buf += 4;
+			*(u32 *)buf = l2;
+			buf += 4;
 			length -= 8;
 			continue;
 		}
@@ -255,13 +258,15 @@
 			l1 = readl(reg_dmadata) & mask;
 			l1 |= readl(reg_dmadata) << 16;
 
-			*((u32 *)buf)++ = l1;
+			*(u32 *)buf = l1;
+			buf += 4;
 			length -= 4;
 			continue;
 		}
 
 		if (status >= 2) {
-			*((u16 *)buf)++ = readl(reg_dmadata);
+			*(u16 *)buf = readl(reg_dmadata);
+			buf += 2;
 			length -= 2;
 		}
 	} while (length);
@@ -305,7 +310,8 @@
 		 * Align buffer.
 		 */
 		if (((u32)buf) & 2 && status >= 2) {
-			writel(*((u16 *)buf)++ << 16, reg_dmadata);
+			writel(*(u16 *)buf << 16, reg_dmadata);
+			buf += 2;
 			status -= 2;
 			length -= 2;
 		}
@@ -313,8 +319,10 @@
 		if (status >= 8) {
 			unsigned long l1, l2;
 
-			l1 = *((u32 *)buf)++;
-			l2 = *((u32 *)buf)++;
+			l1 = *(u32 *)buf;
+			buf += 4;
+			l2 = *(u32 *)buf;
+			buf += 4;
 
 			writel(l1 << 16, reg_dmadata);
 			writel(l1, reg_dmadata);
@@ -327,7 +335,8 @@
 		if (status >= 4) {
 			unsigned long l1;
 
-			l1 = *((u32 *)buf)++;
+			l1 = *(u32 *)buf;
+			buf += 4;
 
 			writel(l1 << 16, reg_dmadata);
 			writel(l1, reg_dmadata);
@@ -336,7 +345,8 @@
 		}
 
 		if (status >= 2) {
-			writel(*((u16 *)buf)++ << 16, reg_dmadata);
+			writel(*(u16 *)buf << 16, reg_dmadata);
+			buf += 2;
 			length -= 2;
 		}
 	} while (length);
diff -Nru a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
--- a/drivers/scsi/arm/fas216.c	2004-06-19 08:53:28 -07:00
+++ b/drivers/scsi/arm/fas216.c	2004-08-18 19:37:53 -07:00
@@ -2681,7 +2681,7 @@
 	 * IRQs after the sleep.
 	 */
 	spin_unlock_irq(info->host->host_lock);
-	scsi_sleep(50 * HZ/100);
+	msleep(50 * 1000/100);
 	spin_lock_irq(info->host->host_lock);
 
 	/*
@@ -2920,7 +2920,7 @@
 	 * scsi standard says wait 250ms
 	 */
 	spin_unlock_irq(info->host->host_lock);
-	scsi_sleep(100*HZ/100);
+	msleep(100*1000/100);
 	spin_lock_irq(info->host->host_lock);
 
 	fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
diff -Nru a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
--- a/drivers/scsi/arm/oak.c	2004-06-19 08:53:31 -07:00
+++ b/drivers/scsi/arm/oak.c	2004-08-24 16:42:28 -07:00
@@ -179,6 +179,7 @@
 	ecard_set_drvdata(ec, NULL);
 	scsi_remove_host(host);
 
+	NCR5380_exit(host);
 	release_region(host->io_port, host->n_io_port);
 	scsi_host_put(host);
 }
diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
--- a/drivers/scsi/cpqfcTSinit.c	2004-05-12 08:46:20 -07:00
+++ b/drivers/scsi/cpqfcTSinit.c	2004-08-24 02:08:35 -07:00
@@ -302,10 +302,16 @@
 				    cpqfc_boards[i].device_id, PciDev)))
     {
 
+      if (pci_enable_device(PciDev)) {
+	printk(KERN_ERR
+		"cpqfc: can't enable PCI device at %s\n", pci_name(PciDev));
+	goto err_continue;
+      }
+
       if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) {
 	printk(KERN_WARNING 
 		"cpqfc: HBA cannot support required DMA mask, skipping.\n");
-	continue;
+	goto err_disable_dev;
       }
 
       // NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes...
@@ -314,8 +320,11 @@
 
       HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) );
       
-      if(HostAdapter == NULL)
-      	continue;
+      if(HostAdapter == NULL) {
+	printk(KERN_WARNING
+		"cpqfc: can't register SCSI HBA, skipping.\n");
+      	goto err_disable_dev;
+      }
       DEBUG_PCI( printk("  HBA found!\n"));
       DEBUG_PCI( printk("  HostAdapter->PciDev->irq = %u\n", PciDev->irq) );
       DEBUG_PCI(printk("  PciDev->baseaddress[0]= %lx\n", 
@@ -367,9 +376,8 @@
 	               DEV_NAME,
 		       HostAdapter) )
       {
-	printk(" IRQ %u already used\n", HostAdapter->irq);
-        scsi_unregister( HostAdapter);
-	continue;
+	printk(KERN_WARNING "cpqfc: IRQ %u already used\n", HostAdapter->irq);
+	goto err_unregister;
       }
 
       // Since we have two 256-byte I/O port ranges (upper
@@ -377,22 +385,17 @@
       if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseU,
       	                   0xff, DEV_NAME ) )
       {
-	printk("  cpqfcTS address in use: %x\n", 
+	printk(KERN_WARNING "cpqfc: address in use: %x\n",
 			cpqfcHBAdata->fcChip.Registers.IOBaseU);
-	free_irq( HostAdapter->irq, HostAdapter);
-        scsi_unregister( HostAdapter);
-	continue;
+	goto err_free_irq;
       }	
       
       if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL,
       			   0xff, DEV_NAME ) )
       {
-  	printk("  cpqfcTS address in use: %x\n", 
+  	printk(KERN_WARNING "cpqfc: address in use: %x\n",
 	      			cpqfcHBAdata->fcChip.Registers.IOBaseL);
-	release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff );
-	free_irq( HostAdapter->irq, HostAdapter);
-        scsi_unregister( HostAdapter);
-	continue;
+	goto err_release_region_U;
       }	
       
       // OK, we have grabbed everything we need now.
@@ -424,7 +427,7 @@
       // now initialize our hardware...
       if (cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1)) {
 	printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.\n");
-	// FIXME: might want to do something better than nothing here.
+	goto err_release_region_L;
       }
 
       cpqfcHBAdata->fcStatsTime = jiffies;  // (for FC Statistics delta)
@@ -455,6 +458,21 @@
       spin_lock_irq(HostAdapter->host_lock);
       NumberOfAdapters++; 
       spin_unlock_irq(HostAdapter->host_lock);
+
+      continue;
+
+err_release_region_L:
+      release_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff );
+err_release_region_U:
+      release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff );
+err_free_irq:
+      free_irq( HostAdapter->irq, HostAdapter);
+err_unregister:
+      scsi_unregister( HostAdapter);
+err_disable_dev:
+      pci_disable_device( PciDev );
+err_continue:
+      continue;
     } // end of while()
   }
 
@@ -811,6 +829,7 @@
       cpqfcHBAdata->fcChip.Registers.ReMapMemBase)
     vfree( cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
 */
+  pci_disable_device( cpqfcHBAdata->PciDev);
 
   LEAVE("cpqfcTS_release");
   return 0;
diff -Nru a/drivers/scsi/dc390.h b/drivers/scsi/dc390.h
--- a/drivers/scsi/dc390.h	2004-05-27 15:57:23 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,32 +0,0 @@
-/***********************************************************************
- *	FILE NAME : DC390.H					       *
- *	     BY   : C.L. Huang					       *
- *	Description: Device Driver for Tekram DC-390(T) PCI SCSI       *
- *		     Bus Master Host Adapter			       *
- ***********************************************************************/
-/* $Id: dc390.h,v 2.43.2.22 2000/12/20 00:39:36 garloff Exp $ */
-
-/*
- * DC390/AMD 53C974 driver, header file
- */
-
-#ifndef DC390_H
-#define DC390_H
-
-#include <linux/version.h>
-
-#define DC390_BANNER "Tekram DC390/AM53C974"
-#define DC390_VERSION "2.1d 2004-05-27"
-
-/* We don't have eh_abort_handler, eh_device_reset_handler, 
- * eh_bus_reset_handler, eh_host_reset_handler yet! 
- * So long: Use old exception handling :-( */
-#define OLD_EH
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION (2,1,70) || defined (OLD_EH)
-# define NEW_EH
-#else
-# define NEW_EH use_new_eh_code: 1,
-# define USE_NEW_EH
-#endif
-#endif /* DC390_H */
diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
--- a/drivers/scsi/dc395x.c	2004-06-06 05:27:30 -07:00
+++ b/drivers/scsi/dc395x.c	2004-07-15 15:21:32 -07:00
@@ -376,6 +376,8 @@
 static void reselect(struct AdapterCtlBlk *acb);
 static u8 start_scsi(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
+static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
+		struct ScsiReqBlk *srb);
 static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
 static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_code,
@@ -384,13 +386,11 @@
 static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb);
 static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb,
 		struct ScsiReqBlk *srb);
-static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
-		struct ScsiReqBlk *srb);
 static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
 static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
-static inline void set_xfer_rate(struct AdapterCtlBlk *acb,
+static void set_xfer_rate(struct AdapterCtlBlk *acb,
 		struct DeviceCtlBlk *dcb);
 static void waiting_timeout(unsigned long ptr);
 
@@ -1676,6 +1676,23 @@
 }
 
 
+#define DC395x_ENABLE_MSGOUT \
+ DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \
+ srb->state |= SRB_MSGOUT
+
+
+/* abort command */
+static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
+		struct ScsiReqBlk *srb)
+{
+	srb->msgout_buf[0] = ABORT;
+	srb->msg_count = 1;
+	DC395x_ENABLE_MSGOUT;
+	srb->state &= ~SRB_MSGIN;
+	srb->state |= SRB_MSGOUT;
+}
+
+
 /**
  * dc395x_handle_interrupt - Handle an interrupt that has been confirmed to
  *                           have been triggered for this card.
@@ -2583,11 +2600,6 @@
 	return 1;
 }
 
-#define DC395x_ENABLE_MSGOUT \
- DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \
- srb->state |= SRB_MSGOUT
-
-
 /* reject_msg */
 static inline void msgin_reject(struct AdapterCtlBlk *acb,
 		struct ScsiReqBlk *srb)
@@ -2600,18 +2612,6 @@
 	dprintkl(KERN_INFO, "msgin_reject: 0x%02x <%02i-%i>\n",
 		srb->msgin_buf[0],
 		srb->dcb->target_id, srb->dcb->target_lun);
-}
-
-
-/* abort command */
-static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
-		struct ScsiReqBlk *srb)
-{
-	srb->msgout_buf[0] = ABORT;
-	srb->msg_count = 1;
-	DC395x_ENABLE_MSGOUT;
-	srb->state &= ~SRB_MSGIN;
-	srb->state |= SRB_MSGOUT;
 }
 
 
diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
--- a/drivers/scsi/dmx3191d.c	2004-05-12 08:46:20 -07:00
+++ b/drivers/scsi/dmx3191d.c	2004-08-24 16:42:28 -07:00
@@ -106,9 +106,10 @@
 
 static int dmx3191d_release_resources(struct Scsi_Host *instance)
 {
-	release_region(instance->io_port, DMX3191D_REGION);
 	if(instance->irq!=SCSI_IRQ_NONE)
 		free_irq(instance->irq, instance);
+	NCR5380_exit(instance);
+	release_region(instance->io_port, DMX3191D_REGION);
 
 	return 0;
 }
diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
--- a/drivers/scsi/dtc.c	2004-05-12 08:46:20 -07:00
+++ b/drivers/scsi/dtc.c	2004-08-24 16:42:28 -07:00
@@ -451,6 +451,7 @@
 {
 	if (shost->irq)
 		free_irq(shost->irq, NULL);
+	NCR5380_exit(shost);
 	if (shost->io_port && shost->n_io_port)
 		release_region(shost->io_port, shost->n_io_port);
 	scsi_unregister(shost);
diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
--- a/drivers/scsi/eata_pio.c	2004-07-26 14:38:51 -07:00
+++ b/drivers/scsi/eata_pio.c	2004-08-04 19:31:42 -07:00
@@ -59,6 +59,8 @@
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/spinlock.h>
+#include <linux/delay.h>
+
 #include <asm/io.h>
 
 #include <scsi/scsi.h>
@@ -511,8 +513,7 @@
 	HD(cmd)->state = RESET;
 
 	spin_unlock_irq(host->host_lock);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(3 * HZ);
+	msleep(3000);
 	spin_lock_irq(host->host_lock);
 
 	DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit));
diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
--- a/drivers/scsi/fd_mcs.c	2004-06-18 13:44:28 -07:00
+++ b/drivers/scsi/fd_mcs.c	2004-08-03 21:30:02 -07:00
@@ -78,6 +78,7 @@
  **************************************************************************/
 
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/errno.h>
@@ -288,7 +289,7 @@
 
 static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
-static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
+static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 
 /* host information */
 static int found = 0;
@@ -297,16 +298,19 @@
 static int user_fifo_count = 0;
 static int user_fifo_size = 0;
 
-static void fd_mcs_setup(char *str, int *ints)
+static int __init fd_mcs_setup(char *str)
 {
 	static int done_setup = 0;
+	int ints[3];
 
 	if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) {
 		printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n");
+		return 0;
 	}
 
 	user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
 	user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
+	return 1;
 }
 
 __setup("fd_mcs=", fd_mcs_setup);
@@ -391,7 +395,7 @@
 			} else {
 				bios = addresses[pos2 >> 6];
 				port = ports[(pos2 >> 4) & 0x03];
-				irq = ints[(pos2 >> 1) & 0x07];
+				irq = interrupts[(pos2 >> 1) & 0x07];
 			}
 
 			if (irq) {
diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
--- a/drivers/scsi/fdomain.c	2004-08-02 01:00:43 -07:00
+++ b/drivers/scsi/fdomain.c	2004-08-25 18:50:07 -07:00
@@ -733,17 +733,20 @@
       printk( " %x,", base );
 #endif
 
-      for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
-	 if (base == ports[i])
-	       ++flag;
+      for (i = 0; i < PORT_COUNT; i++) {
+	if (base == ports[i]) {
+		if (!request_region(base, 0x10, "fdomain"))
+			break;
+		if (!fdomain_is_valid_port(base)) {
+			release_region(base, 0x10);
+			break;
+		}
+		*irq    = fdomain_get_irq( base );
+		*iobase = base;
+		return 1;
+	}
       }
 
-      if (flag && fdomain_is_valid_port( base )) {
-	 *irq    = fdomain_get_irq( base );
-	 *iobase = base;
-	 return 1;
-      }
-      
       /* This is a bad sign.  It usually means that someone patched the
 	 BIOS signature list (the signatures variable) to contain a BIOS
 	 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */
@@ -764,7 +767,7 @@
 
    for (i = 0; i < PORT_COUNT; i++) {
       base = ports[i];
-      if (check_region( base, 0x10 )) {
+      if (!request_region(base, 0x10, "fdomain")) {
 #if DEBUG_DETECT
 	 printk( " (%x inuse),", base );
 #endif
@@ -773,7 +776,10 @@
 #if DEBUG_DETECT
       printk( " %x,", base );
 #endif
-      if ((flag = fdomain_is_valid_port( base ))) break;
+      flag = fdomain_is_valid_port(base);
+      if (flag)
+	break;
+      release_region(base, 0x10);
    }
 
 #if DEBUG_DETECT
@@ -832,6 +838,9 @@
    pci_base = pci_resource_start(pdev, 0);
    pci_irq = pdev->irq;
 
+   if (!request_region( pci_base, 0x10, "fdomain" ))
+	return 0;
+
    /* Now we have the I/O base address and interrupt from the PCI
       configuration registers. */
 
@@ -844,8 +853,9 @@
 	   " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
 #endif
 
-   if (!fdomain_is_valid_port( *iobase )) {
+   if (!fdomain_is_valid_port(pci_base)) {
       printk(KERN_ERR "scsi: <fdomain> PCI card detected, but driver not loaded (invalid port)\n" );
+      release_region(pci_base, 0x10);
       return 0;
    }
 
@@ -870,10 +880,16 @@
       printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
 	      port_base, interrupt_level );
 #endif
+      if (!request_region(port_base, 0x10, "fdomain")) {
+	 printk( "scsi: <fdomain> port 0x%x is busy\n", port_base );
+	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
+	 return NULL;
+      }
       if (!fdomain_is_valid_port( port_base )) {
 	 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
 		 port_base );
 	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
+	 release_region(port_base, 0x10);
 	 return NULL;
       }
    } else {
@@ -915,6 +931,7 @@
       if (setup_called) {
 	 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
       }
+      release_region(port_base, 0x10);
       return NULL;
    }
 
@@ -935,8 +952,10 @@
    get resources.  */
 
    shpnt = scsi_register( tpnt, 0 );
-   if(shpnt == NULL)
+   if(shpnt == NULL) {
+	release_region(port_base, 0x10);
    	return NULL;
+   }
    shpnt->irq = interrupt_level;
    shpnt->io_port = port_base;
    scsi_set_device(shpnt, &pdev->dev);
@@ -946,6 +965,7 @@
    /* Log IRQ with kernel */   
    if (!interrupt_level) {
       printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
+      release_region(port_base, 0x10);
       return NULL;
    } else {
       /* Register the IRQ with the kernel */
@@ -967,13 +987,10 @@
 	    printk(KERN_ERR "                Send mail to faith@acm.org\n" );
 	 }
 	 printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
+         release_region(port_base, 0x10);
 	 return NULL;
       }
    }
-
-   /* Log I/O ports with kernel */
-   request_region( port_base, 0x10, "fdomain" );
-
    return shpnt;
 }
 
diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
--- a/drivers/scsi/g_NCR5380.c	2004-07-26 14:22:32 -07:00
+++ b/drivers/scsi/g_NCR5380.c	2004-08-24 16:42:28 -07:00
@@ -501,6 +501,10 @@
 {
 	NCR5380_local_declare();
 	NCR5380_setup(instance);
+	
+	if (instance->irq != SCSI_IRQ_NONE)
+		free_irq(instance->irq, NULL);
+	NCR5380_exit(instance);
 
 #ifndef CONFIG_SCSI_G_NCR5380_MEM
 	release_region(instance->NCR5380_instance_name, instance->n_io_port);
@@ -508,8 +512,6 @@
 	release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size);
 #endif
 
-	if (instance->irq != SCSI_IRQ_NONE)
-		free_irq(instance->irq, NULL);
 
 	return 0;
 }
diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
--- a/drivers/scsi/gdth.c	2004-06-19 08:26:00 -07:00
+++ b/drivers/scsi/gdth.c	2004-08-09 12:03:02 -07:00
@@ -618,9 +618,6 @@
 };
 
 /* __initfunc, __initdata macros */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define __devinitdata
-#endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 #define GDTH_INITFUNC(type, func)       type __init func 
 #include <linux/init.h>
diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	2004-06-19 07:35:38 -07:00
+++ b/drivers/scsi/hosts.c	2004-08-11 10:35:07 -07:00
@@ -75,9 +75,9 @@
  **/
 void scsi_remove_host(struct Scsi_Host *shost)
 {
+	scsi_forget_host(shost);
 	scsi_host_cancel(shost, 0);
 	scsi_proc_host_rm(shost);
-	scsi_forget_host(shost);
 
 	set_bit(SHOST_DEL, &shost->shost_state);
 
diff -Nru a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/Makefile	2004-07-16 15:50:35 -07:00
@@ -0,0 +1,5 @@
+obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
+
+ibmvscsic-y			+= ibmvscsi.o
+ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
+ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
diff -Nru a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c	2004-07-28 14:33:14 -07:00
@@ -0,0 +1,1393 @@
+/* ------------------------------------------------------------
+ * ibmvscsi.c
+ * (C) Copyright IBM Corporation 1994, 2004
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.com)
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ * ------------------------------------------------------------
+ * Emulation of a SCSI host adapter for Virtual I/O devices
+ *
+ * This driver supports the SCSI adapter implemented by the IBM
+ * Power5 firmware.  That SCSI adapter is not a physical adapter,
+ * but allows Linux SCSI peripheral drivers to directly
+ * access devices in another logical partition on the physical system.
+ *
+ * The virtual adapter(s) are present in the open firmware device
+ * tree just like real adapters.
+ *
+ * One of the capabilities provided on these systems is the ability
+ * to DMA between partitions.  The architecture states that for VSCSI,
+ * the server side is allowed to DMA to and from the client.  The client
+ * is never trusted to DMA to or from the server directly.
+ *
+ * Messages are sent between partitions on a "Command/Response Queue" 
+ * (CRQ), which is just a buffer of 16 byte entries in the receiver's 
+ * Senders cannot access the buffer directly, but send messages by
+ * making a hypervisor call and passing in the 16 bytes.  The hypervisor
+ * puts the message in the next 16 byte space in round-robbin fashion,
+ * turns on the high order bit of the message (the valid bit), and 
+ * generates an interrupt to the receiver (if interrupts are turned on.) 
+ * The receiver just turns off the valid bit when they have copied out
+ * the message.
+ *
+ * The VSCSI client builds a SCSI Remote Protocol (SRP) Information Unit
+ * (IU) (as defined in the T10 standard available at www.t10.org), gets 
+ * a DMA address for the message, and sends it to the server as the
+ * payload of a CRQ message.  The server DMAs the SRP IU and processes it,
+ * including doing any additional data transfers.  When it is done, it
+ * DMAs the SRP response back to the same address as the request came from,
+ * and sends a CRQ message back to inform the client that the request has
+ * completed.
+ *
+ * Note that some of the underlying infrastructure is different between
+ * machines conforming to the "RS/6000 Platform Architecture" (RPA) and
+ * the older iSeries hypervisor models.  To support both, some low level
+ * routines have been broken out into rpa_vscsi.c and iseries_vscsi.c.
+ * The Makefile should pick one, not two, not zero, of these.
+ *
+ * TODO: This is currently pretty tied to the IBM i/pSeries hypervisor
+ * interfaces.  It would be really nice to abstract this above an RDMA
+ * layer.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <asm/vio.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include "ibmvscsi.h"
+
+/* The values below are somewhat arbitrary default values, but 
+ * OS/400 will use 3 busses (disks, CDs, tapes, I think.)
+ * Note that there are 3 bits of channel value, 6 bits of id, and
+ * 5 bits of LUN.
+ */
+static int max_id = 64;
+static int max_channel = 3;
+static int init_timeout = 5;
+static int max_requests = 50;
+
+#define IBMVSCSI_VERSION "1.5.1"
+
+MODULE_DESCRIPTION("IBM Virtual SCSI");
+MODULE_AUTHOR("Dave Boutcher");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(IBMVSCSI_VERSION);
+
+module_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_id, "Largest ID value for each channel");
+module_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_channel, "Largest channel value");
+module_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds");
+module_param_named(max_requests, max_requests, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter");
+
+/* ------------------------------------------------------------
+ * Routines for the event pool and event structs
+ */
+/**
+ * initialize_event_pool: - Allocates and initializes the event pool for a host
+ * @pool:	event_pool to be initialized
+ * @size:	Number of events in pool
+ * @hostdata:	ibmvscsi_host_data who owns the event pool
+ *
+ * Returns zero on success.
+*/
+static int initialize_event_pool(struct event_pool *pool,
+				 int size, struct ibmvscsi_host_data *hostdata)
+{
+	int i;
+
+	pool->size = size;
+	pool->next = 0;
+	pool->events = kmalloc(pool->size * sizeof(*pool->events), GFP_KERNEL);
+	if (!pool->events)
+		return -ENOMEM;
+	memset(pool->events, 0x00, pool->size * sizeof(*pool->events));
+
+	pool->iu_storage =
+	    dma_alloc_coherent(hostdata->dev,
+			       pool->size * sizeof(*pool->iu_storage),
+			       &pool->iu_token, 0);
+	if (!pool->iu_storage) {
+		kfree(pool->events);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < pool->size; ++i) {
+		struct srp_event_struct *evt = &pool->events[i];
+		memset(&evt->crq, 0x00, sizeof(evt->crq));
+		atomic_set(&evt->free, 1);
+		evt->crq.valid = 0x80;
+		evt->crq.IU_length = sizeof(*evt->xfer_iu);
+		evt->crq.IU_data_ptr = pool->iu_token + 
+			sizeof(*evt->xfer_iu) * i;
+		evt->xfer_iu = pool->iu_storage + i;
+		evt->hostdata = hostdata;
+	}
+
+	return 0;
+}
+
+/**
+ * release_event_pool: - Frees memory of an event pool of a host
+ * @pool:	event_pool to be released
+ * @hostdata:	ibmvscsi_host_data who owns the even pool
+ *
+ * Returns zero on success.
+*/
+static void release_event_pool(struct event_pool *pool,
+			       struct ibmvscsi_host_data *hostdata)
+{
+	int i, in_use = 0;
+	for (i = 0; i < pool->size; ++i)
+		if (atomic_read(&pool->events[i].free) != 1)
+			++in_use;
+	if (in_use)
+		printk(KERN_WARNING
+		       "ibmvscsi: releasing event pool with %d "
+		       "events still in use?\n", in_use);
+	kfree(pool->events);
+	dma_free_coherent(hostdata->dev,
+			  pool->size * sizeof(*pool->iu_storage),
+			  pool->iu_storage, pool->iu_token);
+}
+
+/**
+ * valid_event_struct: - Determines if event is valid.
+ * @pool:	event_pool that contains the event
+ * @evt:	srp_event_struct to be checked for validity
+ *
+ * Returns zero if event is invalid, one otherwise.
+*/
+static int valid_event_struct(struct event_pool *pool,
+				struct srp_event_struct *evt)
+{
+	int index = evt - pool->events;
+	if (index < 0 || index >= pool->size)	/* outside of bounds */
+		return 0;
+	if (evt != pool->events + index)	/* unaligned */
+		return 0;
+	return 1;
+}
+
+/**
+ * ibmvscsi_free-event_struct: - Changes status of event to "free"
+ * @pool:	event_pool that contains the event
+ * @evt:	srp_event_struct to be modified
+ *
+*/
+static void free_event_struct(struct event_pool *pool,
+				       struct srp_event_struct *evt)
+{
+	if (!valid_event_struct(pool, evt)) {
+		printk(KERN_ERR
+		       "ibmvscsi: Freeing invalid event_struct %p "
+		       "(not in pool %p)\n", evt, pool->events);
+		return;
+	}
+	if (atomic_inc_return(&evt->free) != 1) {
+		printk(KERN_ERR
+		       "ibmvscsi: Freeing event_struct %p "
+		       "which is not in use!\n", evt);
+		return;
+	}
+}
+
+/**
+ * get_evt_struct: - Gets the next free event in pool
+ * @pool:	event_pool that contains the events to be searched
+ *
+ * Returns the next event in "free" state, and NULL if none are free.
+ * Note that no synchronization is done here, we assume the host_lock
+ * will syncrhonze things.
+*/
+static struct srp_event_struct *get_event_struct(struct event_pool *pool)
+{
+	int i;
+	int poolsize = pool->size;
+	int offset = pool->next;
+
+	for (i = 0; i < poolsize; i++) {
+		offset = (offset + 1) % poolsize;
+		if (!atomic_dec_if_positive(&pool->events[offset].free)) {
+			pool->next = offset;
+			return &pool->events[offset];
+		}
+	}
+
+	printk(KERN_ERR "ibmvscsi: found no event struct in pool!\n");
+	return NULL;
+}
+
+/**
+ * init_event_struct: Initialize fields in an event struct that are always 
+ *                    required.
+ * @evt:        The event
+ * @done:       Routine to call when the event is responded to
+ * @format:     SRP or MAD format
+ * @timeout:    timeout value set in the CRQ
+ */
+static void init_event_struct(struct srp_event_struct *evt_struct,
+			      void (*done) (struct srp_event_struct *),
+			      u8 format,
+			      int timeout)
+{
+	evt_struct->cmnd = NULL;
+	evt_struct->cmnd_done = NULL;
+	evt_struct->crq.format = format;
+	evt_struct->crq.timeout = timeout;
+	evt_struct->done = done;
+}
+
+/* ------------------------------------------------------------
+ * Routines for receiving SCSI responses from the hosting partition
+ */
+
+/**
+ * set_srp_direction: Set the fields in the srp related to data
+ *     direction and number of buffers based on the direction in
+ *     the scsi_cmnd and the number of buffers
+ */
+static void set_srp_direction(struct scsi_cmnd *cmd,
+			      struct srp_cmd *srp_cmd, 
+			      int numbuf)
+{
+	if (numbuf == 0)
+		return;
+	
+	if (numbuf == 1) {
+		if (cmd->sc_data_direction == DMA_TO_DEVICE)
+			srp_cmd->data_out_format = SRP_DIRECT_BUFFER;
+		else 
+			srp_cmd->data_in_format = SRP_DIRECT_BUFFER;
+	} else {
+		if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+			srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
+			srp_cmd->data_out_count = numbuf;
+		} else {
+			srp_cmd->data_in_format = SRP_INDIRECT_BUFFER;
+			srp_cmd->data_in_count = numbuf;
+		}
+	}
+}
+
+/**
+ * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format
+ * @cmd:	srp_cmd whose additional_data member will be unmapped
+ * @dev:	device for which the memory is mapped
+ *
+*/
+static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
+{
+	int i;
+
+	if ((cmd->data_out_format == SRP_NO_BUFFER) &&
+	    (cmd->data_in_format == SRP_NO_BUFFER))
+		return;
+	else if ((cmd->data_out_format == SRP_DIRECT_BUFFER) ||
+		 (cmd->data_in_format == SRP_DIRECT_BUFFER)) {
+		struct memory_descriptor *data =
+			(struct memory_descriptor *)cmd->additional_data;
+		dma_unmap_single(dev, data->virtual_address, data->length,
+				 DMA_BIDIRECTIONAL);
+	} else {
+		struct indirect_descriptor *indirect =
+			(struct indirect_descriptor *)cmd->additional_data;
+		int num_mapped = indirect->head.length / 
+			sizeof(indirect->list[0]);
+		for (i = 0; i < num_mapped; ++i) {
+			struct memory_descriptor *data = &indirect->list[i];
+			dma_unmap_single(dev,
+					 data->virtual_address,
+					 data->length, DMA_BIDIRECTIONAL);
+		}
+	}
+}
+
+/**
+ * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields
+ * @cmd:	Scsi_Cmnd with the scatterlist
+ * @srp_cmd:	srp_cmd that contains the memory descriptor
+ * @dev:	device for which to map dma memory
+ *
+ * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd.
+ * Returns 1 on success.
+*/
+static int map_sg_data(struct scsi_cmnd *cmd,
+		       struct srp_cmd *srp_cmd, struct device *dev)
+{
+
+	int i, sg_mapped;
+	u64 total_length = 0;
+	struct scatterlist *sg = cmd->request_buffer;
+	struct memory_descriptor *data =
+	    (struct memory_descriptor *)srp_cmd->additional_data;
+	struct indirect_descriptor *indirect =
+	    (struct indirect_descriptor *)data;
+
+	sg_mapped = dma_map_sg(dev, sg, cmd->use_sg, DMA_BIDIRECTIONAL);
+
+	if (sg_mapped == 0)
+		return 0;
+
+	set_srp_direction(cmd, srp_cmd, sg_mapped);
+
+	/* special case; we can use a single direct descriptor */
+	if (sg_mapped == 1) {
+		data->virtual_address = sg_dma_address(&sg[0]);
+		data->length = sg_dma_len(&sg[0]);
+		data->memory_handle = 0;
+		return 1;
+	}
+
+	if (sg_mapped > MAX_INDIRECT_BUFS) {
+		printk(KERN_ERR
+		       "ibmvscsi: More than %d mapped sg entries, got %d\n",
+		       MAX_INDIRECT_BUFS, sg_mapped);
+		return 0;
+	}
+
+	indirect->head.virtual_address = 0;
+	indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
+	indirect->head.memory_handle = 0;
+	for (i = 0; i < sg_mapped; ++i) {
+		struct memory_descriptor *descr = &indirect->list[i];
+		struct scatterlist *sg_entry = &sg[i];
+		descr->virtual_address = sg_dma_address(sg_entry);
+		descr->length = sg_dma_len(sg_entry);
+		descr->memory_handle = 0;
+		total_length += sg_dma_len(sg_entry);
+	}
+	indirect->total_length = total_length;
+
+	return 1;
+}
+
+/**
+ * map_single_data: - Maps memory and initializes memory decriptor fields
+ * @cmd:	struct scsi_cmnd with the memory to be mapped
+ * @srp_cmd:	srp_cmd that contains the memory descriptor
+ * @dev:	device for which to map dma memory
+ *
+ * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd.
+ * Returns 1 on success.
+*/
+static int map_single_data(struct scsi_cmnd *cmd,
+			   struct srp_cmd *srp_cmd, struct device *dev)
+{
+	struct memory_descriptor *data =
+	    (struct memory_descriptor *)srp_cmd->additional_data;
+
+	data->virtual_address =
+		dma_map_single(dev, cmd->request_buffer,
+			       cmd->request_bufflen,
+			       DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(data->virtual_address)) {
+		printk(KERN_ERR
+		       "ibmvscsi: Unable to map request_buffer for command!\n");
+		return 0;
+	}
+	data->length = cmd->request_bufflen;
+	data->memory_handle = 0;
+
+	set_srp_direction(cmd, srp_cmd, 1);
+
+	return 1;
+}
+
+/**
+ * map_data_for_srp_cmd: - Calls functions to map data for srp cmds
+ * @cmd:	struct scsi_cmnd with the memory to be mapped
+ * @srp_cmd:	srp_cmd that contains the memory descriptor
+ * @dev:	dma device for which to map dma memory
+ *
+ * Called by scsi_cmd_to_srp_cmd() when converting scsi cmds to srp cmds 
+ * Returns 1 on success.
+*/
+static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
+				struct srp_cmd *srp_cmd, struct device *dev)
+{
+	switch (cmd->sc_data_direction) {
+	case DMA_FROM_DEVICE:
+	case DMA_TO_DEVICE:
+		break;
+	case DMA_NONE:
+		return 1;
+	case DMA_BIDIRECTIONAL:
+		printk(KERN_ERR
+		       "ibmvscsi: Can't map DMA_BIDIRECTIONAL to read/write\n");
+		return 0;
+	default:
+		printk(KERN_ERR
+		       "ibmvscsi: Unknown data direction 0x%02x; can't map!\n",
+		       cmd->sc_data_direction);
+		return 0;
+	}
+
+	if (!cmd->request_buffer)
+		return 1;
+	if (cmd->use_sg)
+		return map_sg_data(cmd, srp_cmd, dev);
+	return map_single_data(cmd, srp_cmd, dev);
+}
+
+/* ------------------------------------------------------------
+ * Routines for sending and receiving SRPs
+ */
+/**
+ * ibmvscsi_send_srp_event: - Transforms event to u64 array and calls send_crq()
+ * @evt_struct:	evt_struct to be sent
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ * Returns the value returned from ibmvscsi_send_crq(). (Zero for success)
+ * Note that this routine assumes that host_lock is held for synchronization
+*/
+static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
+				   struct ibmvscsi_host_data *hostdata)
+{
+	struct scsi_cmnd *cmnd = evt_struct->cmnd;
+	u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
+	int rc;
+
+	/* If we have exhausted our request limit, just fail this request.
+	 * Note that there are rare cases involving driver generated requests 
+	 * (such as task management requests) that the mid layer may think we
+	 * can handle more requests (can_queue) when we actually can't
+	 */
+	if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
+	    (atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
+		/* See if the adapter is disabled */
+		if (atomic_read(&hostdata->request_limit) < 0) {
+			if (cmnd)
+				cmnd->result = DID_ERROR << 16;
+			if (evt_struct->cmnd_done)
+				evt_struct->cmnd_done(cmnd);
+			unmap_cmd_data(&evt_struct->iu.srp.cmd,
+				       hostdata->dev);
+			free_event_struct(&hostdata->pool, evt_struct);
+			return 0;
+		} else {
+			printk("ibmvscsi: Warning, request_limit exceeded\n");
+			unmap_cmd_data(&evt_struct->iu.srp.cmd,
+				       hostdata->dev);
+			free_event_struct(&hostdata->pool, evt_struct);
+			return SCSI_MLQUEUE_HOST_BUSY;
+		}
+	}
+
+	/* Copy the IU into the transfer area */
+	*evt_struct->xfer_iu = evt_struct->iu;
+	evt_struct->xfer_iu->srp.generic.tag = (u64)evt_struct;
+
+	/* Add this to the sent list.  We need to do this 
+	 * before we actually send 
+	 * in case it comes back REALLY fast
+	 */
+	list_add_tail(&evt_struct->list, &hostdata->sent);
+
+	if ((rc =
+	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
+		list_del(&evt_struct->list);
+
+		cmnd = evt_struct->cmnd;
+		printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
+		       rc);
+		unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+		free_event_struct(&hostdata->pool, evt_struct);
+		if (cmnd)
+			cmnd->result = DID_ERROR << 16;
+		if (evt_struct->cmnd_done)
+			evt_struct->cmnd_done(cmnd);
+	}
+
+	return 0;
+}
+
+/**
+ * handle_cmd_rsp: -  Handle responses from commands
+ * @evt_struct:	srp_event_struct to be handled
+ *
+ * Used as a callback by when sending scsi cmds.
+ * Gets called by ibmvscsi_handle_crq()
+*/
+static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
+{
+	struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
+	struct scsi_cmnd *cmnd = evt_struct->cmnd;
+
+	if (cmnd) {
+		cmnd->result = rsp->status;
+		if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
+			memcpy(cmnd->sense_buffer,
+			       rsp->sense_and_response_data,
+			       rsp->sense_data_list_length);
+		unmap_cmd_data(&evt_struct->iu.srp.cmd, 
+			       evt_struct->hostdata->dev);
+
+		if (rsp->doover)
+			cmnd->resid = rsp->data_out_residual_count;
+		else if (rsp->diover)
+			cmnd->resid = rsp->data_in_residual_count;
+	}
+
+	if (evt_struct->cmnd_done)
+		evt_struct->cmnd_done(cmnd);
+}
+
+/**
+ * lun_from_dev: - Returns the lun of the scsi device
+ * @dev:	struct scsi_device
+ *
+*/
+static inline u16 lun_from_dev(struct scsi_device *dev)
+{
+	return (0x2 << 14) | (dev->id << 8) | (dev->channel << 5) | dev->lun;
+}
+
+/**
+ * ibmvscsi_queue: - The queuecommand function of the scsi template 
+ * @cmd:	struct scsi_cmnd to be executed
+ * @done:	Callback function to be called when cmd is completed
+*/
+static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
+				 void (*done) (struct scsi_cmnd *))
+{
+	struct srp_cmd *srp_cmd;
+	struct srp_event_struct *evt_struct;
+	struct ibmvscsi_host_data *hostdata =
+		(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
+	u16 lun = lun_from_dev(cmnd->device);
+
+	evt_struct = get_event_struct(&hostdata->pool);
+	if (!evt_struct)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
+	init_event_struct(evt_struct,
+			  handle_cmd_rsp,
+			  VIOSRP_SRP_FORMAT,
+			  cmnd->timeout);
+
+	evt_struct->cmnd = cmnd;
+	evt_struct->cmnd_done = done;
+
+	/* Set up the actual SRP IU */
+	srp_cmd = &evt_struct->iu.srp.cmd;
+	memset(srp_cmd, 0x00, sizeof(*srp_cmd));
+	srp_cmd->type = SRP_CMD_TYPE;
+	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+	srp_cmd->lun = ((u64) lun) << 48;
+
+	if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) {
+		printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
+		free_event_struct(&hostdata->pool, evt_struct);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	/* Fix up dma address of the buffer itself */
+	if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
+	    (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) {
+		struct indirect_descriptor *indirect =
+		    (struct indirect_descriptor *)srp_cmd->additional_data;
+		indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +
+		    offsetof(struct srp_cmd, additional_data) +
+		    offsetof(struct indirect_descriptor, list);
+	}
+
+	return ibmvscsi_send_srp_event(evt_struct, hostdata);
+}
+
+/* ------------------------------------------------------------
+ * Routines for driver initialization
+ */
+/**
+ * adapter_info_rsp: - Handle response to MAD adapter info request
+ * @evt_struct:	srp_event_struct with the response
+ *
+ * Used as a "done" callback by when sending adapter_info. Gets called
+ * by ibmvscsi_handle_crq()
+*/
+static void adapter_info_rsp(struct srp_event_struct *evt_struct)
+{
+	struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
+	dma_unmap_single(hostdata->dev,
+			 evt_struct->iu.mad.adapter_info.buffer,
+			 evt_struct->iu.mad.adapter_info.common.length,
+			 DMA_BIDIRECTIONAL);
+
+	if (evt_struct->xfer_iu->mad.adapter_info.common.status) {
+		printk("ibmvscsi: error %d getting adapter info\n",
+		       evt_struct->xfer_iu->mad.adapter_info.common.status);
+	} else {
+		printk("ibmvscsi: host srp version: %s, "
+		       "host partition %s (%d), OS %d\n",
+		       hostdata->madapter_info.srp_version,
+		       hostdata->madapter_info.partition_name,
+		       hostdata->madapter_info.partition_number,
+		       hostdata->madapter_info.os_type);
+	}
+}
+
+/**
+ * send_mad_adapter_info: - Sends the mad adapter info request
+ *      and stores the result so it can be retrieved with
+ *      sysfs.  We COULD consider causing a failure if the
+ *      returned SRP version doesn't match ours.
+ * @hostdata:	ibmvscsi_host_data of host
+ * 
+ * Returns zero if successful.
+*/
+static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
+{
+	struct viosrp_adapter_info *req;
+	struct srp_event_struct *evt_struct;
+	
+	memset(&hostdata->madapter_info, 0x00, sizeof(hostdata->madapter_info));
+	
+	evt_struct = get_event_struct(&hostdata->pool);
+	if (!evt_struct) {
+		printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
+		       "for ADAPTER_INFO_REQ!\n");
+		return;
+	}
+
+	init_event_struct(evt_struct,
+			  adapter_info_rsp,
+			  VIOSRP_MAD_FORMAT,
+			  init_timeout * HZ);
+	
+	req = &evt_struct->iu.mad.adapter_info;
+	memset(req, 0x00, sizeof(*req));
+	
+	req->common.type = VIOSRP_ADAPTER_INFO_TYPE;
+	req->common.length = sizeof(hostdata->madapter_info);
+	req->buffer = dma_map_single(hostdata->dev,
+				     &hostdata->madapter_info,
+				     sizeof(hostdata->madapter_info),
+				     DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(req->buffer)) {
+		printk(KERN_ERR
+		       "ibmvscsi: Unable to map request_buffer "
+		       "for adapter_info!\n");
+		free_event_struct(&hostdata->pool, evt_struct);
+		return;
+	}
+	
+	if (ibmvscsi_send_srp_event(evt_struct, hostdata))
+		printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
+};
+
+/**
+ * login_rsp: - Handle response to SRP login request
+ * @evt_struct:	srp_event_struct with the response
+ *
+ * Used as a "done" callback by when sending srp_login. Gets called
+ * by ibmvscsi_handle_crq()
+*/
+static void login_rsp(struct srp_event_struct *evt_struct)
+{
+	struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
+	switch (evt_struct->xfer_iu->srp.generic.type) {
+	case SRP_LOGIN_RSP_TYPE:	/* it worked! */
+		break;
+	case SRP_LOGIN_REJ_TYPE:	/* refused! */
+		printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REQ rejected\n");
+		/* Login failed.  */
+		atomic_set(&hostdata->request_limit, -1);
+		return;
+	default:
+		printk(KERN_ERR
+		       "ibmvscsi: Invalid login response typecode 0x%02x!\n",
+		       evt_struct->xfer_iu->srp.generic.type);
+		/* Login failed.  */
+		atomic_set(&hostdata->request_limit, -1);
+		return;
+	}
+
+	printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
+
+	if (evt_struct->xfer_iu->srp.login_rsp.request_limit_delta >
+	    (max_requests - 2))
+		evt_struct->xfer_iu->srp.login_rsp.request_limit_delta =
+		    max_requests - 2;
+
+	/* Now we know what the real request-limit is */
+	atomic_set(&hostdata->request_limit,
+		   evt_struct->xfer_iu->srp.login_rsp.request_limit_delta);
+
+	hostdata->host->can_queue =
+	    evt_struct->xfer_iu->srp.login_rsp.request_limit_delta - 2;
+
+	if (hostdata->host->can_queue < 1) {
+		printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
+		return;
+	}
+
+	send_mad_adapter_info(hostdata);
+	return;
+}
+
+/**
+ * send_srp_login: - Sends the srp login
+ * @hostdata:	ibmvscsi_host_data of host
+ * 
+ * Returns zero if successful.
+*/
+static int send_srp_login(struct ibmvscsi_host_data *hostdata)
+{
+	int rc;
+	unsigned long flags;
+	struct srp_login_req *login;
+	struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool);
+	if (!evt_struct) {
+		printk(KERN_ERR
+		       "ibmvscsi: couldn't allocate an event for login req!\n");
+		return FAILED;
+	}
+
+	init_event_struct(evt_struct,
+			  login_rsp,
+			  VIOSRP_SRP_FORMAT,
+			  init_timeout * HZ);
+
+	login = &evt_struct->iu.srp.login_req;
+	login->type = SRP_LOGIN_REQ_TYPE;
+	login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
+	login->required_buffer_formats = 0x0006;
+	
+	/* Start out with a request limit of 1, since this is negotiated in
+	 * the login request we are just sending
+	 */
+	atomic_set(&hostdata->request_limit, 1);
+
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
+	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+	return rc;
+};
+
+/**
+ * sync_completion: Signal that a synchronous command has completed
+ * Note that after returning from this call, the evt_struct is freed.
+ * the caller waiting on this completion shouldn't touch the evt_struct
+ * again.
+ */
+static void sync_completion(struct srp_event_struct *evt_struct)
+{
+	complete(&evt_struct->comp);
+}
+
+/**
+ * ibmvscsi_abort: Abort a command...from scsi host template
+ * send this over to the server and wait synchronously for the response
+ */
+static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
+{
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)cmd->device->host->hostdata;
+	struct srp_tsk_mgmt *tsk_mgmt;
+	struct srp_event_struct *evt;
+	struct srp_event_struct *tmp_evt, *found_evt;
+	u16 lun = lun_from_dev(cmd->device);
+
+	/* First, find this command in our sent list so we can figure
+	 * out the correct tag
+	 */
+	found_evt = NULL;
+	list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+		if (tmp_evt->cmnd == cmd) {
+			found_evt = tmp_evt;
+			break;
+		}
+	}
+
+	if (!found_evt) 
+		return FAILED;
+
+	evt = get_event_struct(&hostdata->pool);
+	if (evt == NULL) {
+		printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
+		return FAILED;
+	}
+	
+	init_event_struct(evt,
+			  sync_completion,
+			  VIOSRP_SRP_FORMAT,
+			  init_timeout * HZ);
+
+	tsk_mgmt = &evt->iu.srp.tsk_mgmt;
+	
+	/* Set up an abort SRP command */
+	memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
+	tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+	tsk_mgmt->lun = ((u64) lun) << 48;
+	tsk_mgmt->task_mgmt_flags = 0x01;	/* ABORT TASK */
+	tsk_mgmt->managed_task_tag = (u64) found_evt;
+
+	printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
+	       tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
+
+	init_completion(&evt->comp);
+	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+		printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
+		return FAILED;
+	}
+
+	spin_unlock_irq(hostdata->host->host_lock);
+	wait_for_completion(&evt->comp);
+	spin_lock_irq(hostdata->host->host_lock);
+
+	/* Because we dropped the spinlock above, it's possible
+	 * The event is no longer in our list.  Make sure it didn't
+	 * complete while we were aborting
+	 */
+	found_evt = NULL;
+	list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+		if (tmp_evt->cmnd == cmd) {
+			found_evt = tmp_evt;
+			break;
+		}
+	}
+
+	printk(KERN_INFO
+	       "ibmvscsi: successfully aborted task tag 0x%lx\n",
+	       tsk_mgmt->managed_task_tag);
+
+	if (found_evt == NULL)
+		return SUCCESS;
+
+	cmd->result = (DID_ABORT << 16);
+	list_del(&found_evt->list);
+	unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
+	free_event_struct(&found_evt->hostdata->pool, found_evt);
+	atomic_inc(&hostdata->request_limit);
+	return SUCCESS;
+}
+
+/**
+ * ibmvscsi_eh_device_reset_handler: Reset a single LUN...from scsi host 
+ * template send this over to the server and wait synchronously for the 
+ * response
+ */
+static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
+{
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)cmd->device->host->hostdata;
+
+	struct srp_tsk_mgmt *tsk_mgmt;
+	struct srp_event_struct *evt;
+	struct srp_event_struct *tmp_evt, *pos;
+	u16 lun = lun_from_dev(cmd->device);
+
+	evt = get_event_struct(&hostdata->pool);
+	if (evt == NULL) {
+		printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
+		return FAILED;
+	}
+	
+	init_event_struct(evt,
+			  sync_completion,
+			  VIOSRP_SRP_FORMAT,
+			  init_timeout * HZ);
+
+	tsk_mgmt = &evt->iu.srp.tsk_mgmt;
+
+	/* Set up a lun reset SRP command */
+	memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
+	tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+	tsk_mgmt->lun = ((u64) lun) << 48;
+	tsk_mgmt->task_mgmt_flags = 0x08;	/* LUN RESET */
+
+	printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
+	       tsk_mgmt->lun);
+
+	init_completion(&evt->comp);
+	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+		printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
+		return FAILED;
+	}
+
+	spin_unlock_irq(hostdata->host->host_lock);
+	wait_for_completion(&evt->comp);
+	spin_lock_irq(hostdata->host->host_lock);
+
+	/* We need to find all commands for this LUN that have not yet been
+	 * responded to, and fail them with DID_RESET
+	 */
+	list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
+		if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) {
+			if (tmp_evt->cmnd)
+				tmp_evt->cmnd->result = (DID_RESET << 16);
+			list_del(&tmp_evt->list);
+			unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt->hostdata->dev);
+			free_event_struct(&tmp_evt->hostdata->pool,
+						   tmp_evt);
+			atomic_inc(&hostdata->request_limit);
+			if (tmp_evt->cmnd_done)
+				tmp_evt->cmnd_done(tmp_evt->cmnd);
+			else if (tmp_evt->done)
+				tmp_evt->done(tmp_evt);
+		}
+	}
+	return SUCCESS;
+}
+
+/**
+ * purge_requests: Our virtual adapter just shut down.  purge any sent requests
+ * @hostdata:    the adapter
+ */
+static void purge_requests(struct ibmvscsi_host_data *hostdata)
+{
+	struct srp_event_struct *tmp_evt, *pos;
+	unsigned long flags;
+
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
+	list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
+		list_del(&tmp_evt->list);
+		if (tmp_evt->cmnd) {
+			tmp_evt->cmnd->result = (DID_ERROR << 16);
+			unmap_cmd_data(&tmp_evt->iu.srp.cmd, 
+				       tmp_evt->hostdata->dev);
+			if (tmp_evt->cmnd_done)
+				tmp_evt->cmnd_done(tmp_evt->cmnd);
+		} else {
+			if (tmp_evt->done) {
+				tmp_evt->done(tmp_evt);
+			}
+		}
+		free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
+	}
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+}
+
+/**
+ * ibmvscsi_handle_crq: - Handles and frees received events in the CRQ
+ * @crq:	Command/Response queue
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+*/
+void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+			 struct ibmvscsi_host_data *hostdata)
+{
+	unsigned long flags;
+	struct srp_event_struct *evt_struct =
+	    (struct srp_event_struct *)crq->IU_data_ptr;
+	switch (crq->valid) {
+	case 0xC0:		/* initialization */
+		switch (crq->format) {
+		case 0x01:	/* Initialization message */
+			printk(KERN_INFO "ibmvscsi: partner initialized\n");
+			/* Send back a response */
+			if (ibmvscsi_send_crq(hostdata,
+					      0xC002000000000000LL, 0) == 0) {
+				/* Now login */
+				send_srp_login(hostdata);
+			} else {
+				printk(KERN_ERR
+				       "ibmvscsi: Unable to send init rsp\n");
+			}
+
+			break;
+		case 0x02:	/* Initialization response */
+			printk(KERN_INFO
+			       "ibmvscsi: partner initialization complete\n");
+
+			/* Now login */
+			send_srp_login(hostdata);
+			break;
+		default:
+			printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
+		}
+		return;
+	case 0xFF:		/* Hypervisor telling us the connection is closed */
+		printk(KERN_INFO "ibmvscsi: Virtual adapter failed!\n");
+
+		atomic_set(&hostdata->request_limit, -1);
+		purge_requests(hostdata);
+		ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+		return;
+	case 0x80:		/* real payload */
+		break;
+	default:
+		printk(KERN_ERR
+		       "ibmvscsi: got an invalid message type 0x%02x\n",
+		       crq->valid);
+		return;
+	}
+
+	/* The only kind of payload CRQs we should get are responses to
+	 * things we send. Make sure this response is to something we
+	 * actually sent
+	 */
+	if (!valid_event_struct(&hostdata->pool, evt_struct)) {
+		printk(KERN_ERR
+		       "ibmvscsi: returned correlation_token 0x%p is invalid!\n",
+		       (void *)crq->IU_data_ptr);
+		return;
+	}
+
+	if (crq->format == VIOSRP_SRP_FORMAT)
+		atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
+			   &hostdata->request_limit);
+
+	if (evt_struct->done)
+		evt_struct->done(evt_struct);
+	else
+		printk(KERN_ERR
+		       "ibmvscsi: returned done() is NULL; not running it!\n");
+
+	/*
+	 * Lock the host_lock before messing with these structures, since we
+	 * are running in a task context
+	 */
+	spin_lock_irqsave(evt_struct->hostdata->host->host_lock, flags);
+	list_del(&evt_struct->list);
+	free_event_struct(&evt_struct->hostdata->pool, evt_struct);
+	spin_unlock_irqrestore(evt_struct->hostdata->host->host_lock, flags);
+}
+
+/**
+ * ibmvscsi_get_host_config: Send the command to the server to get host
+ * configuration data.  The data is opaque to us.
+ */
+static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
+				   unsigned char *buffer, int length)
+{
+	struct viosrp_host_config *host_config;
+	struct srp_event_struct *evt_struct;
+	int rc;
+
+	evt_struct = get_event_struct(&hostdata->pool);
+	if (!evt_struct) {
+		printk(KERN_ERR
+		       "ibmvscsi: could't allocate event for HOST_CONFIG!\n");
+		return -1;
+	}
+
+	init_event_struct(evt_struct,
+			  sync_completion,
+			  VIOSRP_MAD_FORMAT,
+			  init_timeout * HZ);
+
+	host_config = &evt_struct->iu.mad.host_config;
+
+	/* Set up a lun reset SRP command */
+	memset(host_config, 0x00, sizeof(*host_config));
+	host_config->common.type = VIOSRP_HOST_CONFIG_TYPE;
+	host_config->common.length = length;
+	host_config->buffer = dma_map_single(hostdata->dev, buffer, length,
+					    DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(host_config->buffer)) {
+		printk(KERN_ERR
+		       "ibmvscsi: dma_mapping error " "getting host config\n");
+		free_event_struct(&hostdata->pool, evt_struct);
+		return -1;
+	}
+
+	init_completion(&evt_struct->comp);
+	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+	if (rc == 0) {
+		wait_for_completion(&evt_struct->comp);
+		dma_unmap_single(hostdata->dev, host_config->buffer,
+				 length, DMA_BIDIRECTIONAL);
+	}
+
+	return rc;
+}
+
+/* ------------------------------------------------------------
+ * sysfs attributes
+ */
+static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%s\n",
+		       hostdata->madapter_info.srp_version);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_srp_version = {
+	.attr = {
+		 .name = "srp_version",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_srp_version,
+};
+
+static ssize_t show_host_partition_name(struct class_device *class_dev,
+					char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%s\n",
+		       hostdata->madapter_info.partition_name);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_partition_name = {
+	.attr = {
+		 .name = "partition_name",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_partition_name,
+};
+
+static ssize_t show_host_partition_number(struct class_device *class_dev,
+					  char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%d\n",
+		       hostdata->madapter_info.partition_number);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_partition_number = {
+	.attr = {
+		 .name = "partition_number",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_partition_number,
+};
+
+static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%d\n",
+		       hostdata->madapter_info.mad_version);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_mad_version = {
+	.attr = {
+		 .name = "mad_version",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_mad_version,
+};
+
+static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%d\n", hostdata->madapter_info.os_type);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_os_type = {
+	.attr = {
+		 .name = "os_type",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_os_type,
+};
+
+static ssize_t show_host_config(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+
+	/* returns null-terminated host config data */
+	if (ibmvscsi_do_host_config(hostdata, buf, PAGE_SIZE) == 0)
+		return strlen(buf);
+	else
+		return 0;
+}
+
+static struct class_device_attribute ibmvscsi_host_config = {
+	.attr = {
+		 .name = "config",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_config,
+};
+
+static struct class_device_attribute *ibmvscsi_attrs[] = {
+	&ibmvscsi_host_srp_version,
+	&ibmvscsi_host_partition_name,
+	&ibmvscsi_host_partition_number,
+	&ibmvscsi_host_mad_version,
+	&ibmvscsi_host_os_type,
+	&ibmvscsi_host_config,
+	NULL
+};
+
+/* ------------------------------------------------------------
+ * SCSI driver registration
+ */
+static struct scsi_host_template driver_template = {
+	.module = THIS_MODULE,
+	.name = "IBM POWER Virtual SCSI Adapter " IBMVSCSI_VERSION,
+	.proc_name = "ibmvscsi",
+	.queuecommand = ibmvscsi_queuecommand,
+	.eh_abort_handler = ibmvscsi_eh_abort_handler,
+	.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+	.cmd_per_lun = 16,
+	.can_queue = 1,		/* Updated after SRP_LOGIN */
+	.this_id = -1,
+	.sg_tablesize = MAX_INDIRECT_BUFS,
+	.use_clustering = ENABLE_CLUSTERING,
+	.shost_attrs = ibmvscsi_attrs,
+};
+
+/**
+ * Called by bus code for each adapter
+ */
+static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+{
+	struct ibmvscsi_host_data *hostdata;
+	struct Scsi_Host *host;
+	struct device *dev = &vdev->dev;
+	unsigned long wait_switch = 0;
+
+	vdev->dev.driver_data = NULL;
+
+	host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
+	if (!host) {
+		printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
+		goto scsi_host_alloc_failed;
+	}
+
+	hostdata = (struct ibmvscsi_host_data *)host->hostdata;
+	memset(hostdata, 0x00, sizeof(*hostdata));
+	INIT_LIST_HEAD(&hostdata->sent);
+	hostdata->host = host;
+	hostdata->dev = dev;
+	atomic_set(&hostdata->request_limit, -1);
+
+	if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
+				    max_requests) != 0) {
+		printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
+		goto init_crq_failed;
+	}
+	if (initialize_event_pool(&hostdata->pool, max_requests, hostdata) != 0) {
+		printk(KERN_ERR "ibmvscsi: couldn't initialize event pool\n");
+		goto init_pool_failed;
+	}
+
+	host->max_lun = 8;
+	host->max_id = max_id;
+	host->max_channel = max_channel;
+
+	if (scsi_add_host(hostdata->host, hostdata->dev))
+		goto add_host_failed;
+
+	/* Try to send an initialization message.  Note that this is allowed
+	 * to fail if the other end is not acive.  In that case we don't
+	 * want to scan
+	 */
+	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0) {
+		/*
+		 * Wait around max init_timeout secs for the adapter to finish
+		 * initializing. When we are done initializing, we will have a
+		 * valid request_limit.  We don't want Linux scanning before
+		 * we are ready.
+		 */
+		for (wait_switch = jiffies + (init_timeout * HZ);
+		     time_before(jiffies, wait_switch) &&
+		     atomic_read(&hostdata->request_limit) < 0;) {
+
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ / 100);
+		}
+
+		/* if we now have a valid request_limit, initiate a scan */
+		if (atomic_read(&hostdata->request_limit) > 0)
+			scsi_scan_host(host);
+	}
+
+	vdev->dev.driver_data = hostdata;
+	return 0;
+
+      add_host_failed:
+	release_event_pool(&hostdata->pool, hostdata);
+      init_pool_failed:
+	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
+      init_crq_failed:
+	scsi_host_put(host);
+      scsi_host_alloc_failed:
+	return -1;
+}
+
+static int ibmvscsi_remove(struct vio_dev *vdev)
+{
+	struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
+	release_event_pool(&hostdata->pool, hostdata);
+	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
+				   max_requests);
+	
+	scsi_remove_host(hostdata->host);
+	scsi_host_put(hostdata->host);
+
+	return 0;
+}
+
+/**
+ * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we 
+ * support.
+ */
+static struct vio_device_id ibmvscsi_device_table[] __devinitdata = {
+	{"vscsi", "IBM,v-scsi"},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table);
+static struct vio_driver ibmvscsi_driver = {
+	.name = "ibmvscsi",
+	.id_table = ibmvscsi_device_table,
+	.probe = ibmvscsi_probe,
+	.remove = ibmvscsi_remove
+};
+
+int __init ibmvscsi_module_init(void)
+{
+	return vio_register_driver(&ibmvscsi_driver);
+}
+
+void __exit ibmvscsi_module_exit(void)
+{
+	vio_unregister_driver(&ibmvscsi_driver);
+}
+
+module_init(ibmvscsi_module_init);
+module_exit(ibmvscsi_module_exit);
diff -Nru a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h	2004-07-16 15:50:36 -07:00
@@ -0,0 +1,108 @@
+/* ------------------------------------------------------------
+ * ibmvscsi.h
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.com)
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ * ------------------------------------------------------------
+ * Emulation of a SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+#ifndef IBMVSCSI_H
+#define IBMVSCSI_H
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include "viosrp.h"
+
+struct scsi_cmnd;
+struct Scsi_Host;
+
+/* Number of indirect bufs...the list of these has to fit in the
+ * additional data of the srp_cmd struct along with the indirect
+ * descriptor
+ */
+#define MAX_INDIRECT_BUFS 10
+
+/* ------------------------------------------------------------
+ * Data Structures
+ */
+/* an RPA command/response transport queue */
+struct crq_queue {
+	struct viosrp_crq *msgs;
+	int size, cur;
+	dma_addr_t msg_token;
+	spinlock_t lock;
+};
+
+/* a unit of work for the hosting partition */
+struct srp_event_struct {
+	union viosrp_iu *xfer_iu;
+	struct scsi_cmnd *cmnd;
+	struct list_head list;
+	void (*done) (struct srp_event_struct *);
+	struct viosrp_crq crq;
+	struct ibmvscsi_host_data *hostdata;
+	atomic_t free;
+	union viosrp_iu iu;
+	void (*cmnd_done) (struct scsi_cmnd *);
+	struct completion comp;
+};
+
+/* a pool of event structs for use */
+struct event_pool {
+	struct srp_event_struct *events;
+	u32 size;
+	int next;
+	union viosrp_iu *iu_storage;
+	dma_addr_t iu_token;
+};
+
+/* all driver data associated with a host adapter */
+struct ibmvscsi_host_data {
+	atomic_t request_limit;
+	struct device *dev;
+	struct event_pool pool;
+	struct crq_queue queue;
+	struct tasklet_struct srp_task;
+	struct list_head sent;
+	struct Scsi_Host *host;
+	struct mad_adapter_info_data madapter_info;
+};
+
+/* routines for managing a command/response queue */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+			    struct ibmvscsi_host_data *hostdata,
+			    int max_requests);
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+				struct ibmvscsi_host_data *hostdata,
+				int max_requests);
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata);
+
+void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+			 struct ibmvscsi_host_data *hostdata);
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+		      u64 word1, u64 word2);
+
+#endif				/* IBMVSCSI_H */
diff -Nru a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c	2004-07-16 15:50:36 -07:00
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------
+ * iSeries_vscsi.c
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.com)
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ * ------------------------------------------------------------
+ * iSeries-specific functions of the SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+
+#include <asm/iSeries/vio.h>
+#include <asm/iSeries/HvLpEvent.h>
+#include <asm/iSeries/HvTypes.h>
+#include <asm/iSeries/HvLpConfig.h>
+#include <asm/vio.h>
+#include <linux/device.h>
+#include "ibmvscsi.h"
+
+/* global variables */
+static struct ibmvscsi_host_data *single_host_data;
+
+/* ------------------------------------------------------------
+ * Routines for direct interpartition interaction
+ */
+struct srp_lp_event {
+	struct HvLpEvent lpevt;	/* 0x00-0x17          */
+	u32 reserved1;		/* 0x18-0x1B; unused  */
+	u16 version;		/* 0x1C-0x1D; unused  */
+	u16 subtype_rc;		/* 0x1E-0x1F; unused  */
+	struct viosrp_crq crq;	/* 0x20-0x3F          */
+};
+
+/** 
+ * standard interface for handling logical partition events.
+ */
+static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
+{
+	struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
+
+	if (!evt) {
+		printk(KERN_ERR "ibmvscsi: received null event\n");
+		return;
+	}
+
+	if (single_host_data == NULL) {
+		printk(KERN_ERR
+		       "ibmvscsi: received event, no adapter present\n");
+		return;
+	}
+
+	ibmvscsi_handle_crq(&evt->crq, single_host_data);
+}
+
+/* ------------------------------------------------------------
+ * Routines for driver initialization
+ */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+			    struct ibmvscsi_host_data *hostdata,
+			    int max_requests)
+{
+	int rc;
+
+	single_host_data = hostdata;
+	rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, 0);
+	if (rc < 0) {
+		printk("viopath_open failed with rc %d in open_event_path\n",
+		       rc);
+		goto viopath_open_failed;
+	}
+
+	rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
+	if (rc < 0) {
+		printk("vio_setHandler failed with rc %d in open_event_path\n",
+		       rc);
+		goto vio_setHandler_failed;
+	}
+	return 0;
+
+      vio_setHandler_failed:
+	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
+      viopath_open_failed:
+	return -1;
+}
+
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+				struct ibmvscsi_host_data *hostdata,
+				int max_requests)
+{
+	vio_clearHandler(viomajorsubtype_scsi);
+	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
+}
+
+/**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ * no-op for iSeries
+ */
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata)
+{
+}
+
+/**
+ * ibmvscsi_send_crq: - Send a CRQ
+ * @hostdata:	the adapter
+ * @word1:	the first 64 bits of the data
+ * @word2:	the second 64 bits of the data
+ */
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+{
+	single_host_data = hostdata;
+	return HvCallEvent_signalLpEventFast(viopath_hostLp,
+					     HvLpEvent_Type_VirtualIo,
+					     viomajorsubtype_scsi,
+					     HvLpEvent_AckInd_NoAck,
+					     HvLpEvent_AckType_ImmediateAck,
+					     viopath_sourceinst(viopath_hostLp),
+					     viopath_targetinst(viopath_hostLp),
+					     0,
+					     VIOVERSION << 16, word1, word2, 0,
+					     0);
+}
diff -Nru a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c	2004-07-16 15:50:36 -07:00
@@ -0,0 +1,260 @@
+/* ------------------------------------------------------------
+ * rpa_vscsi.c
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ * ------------------------------------------------------------
+ * RPA-specific functions of the SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+
+#include <asm/vio.h>
+#include <asm/iommu.h>
+#include <asm/hvcall.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include "ibmvscsi.h"
+
+/* ------------------------------------------------------------
+ * Routines for managing the command/response queue
+ */
+/**
+ * ibmvscsi_handle_event: - Interrupt handler for crq events
+ * @irq:	number of irq to handle, not used
+ * @dev_instance: ibmvscsi_host_data of host that received interrupt
+ * @regs:	pt_regs with registers
+ *
+ * Disables interrupts and schedules srp_task
+ * Always returns IRQ_HANDLED
+ */
+static irqreturn_t ibmvscsi_handle_event(int irq,
+					 void *dev_instance,
+					 struct pt_regs *regs)
+{
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)dev_instance;
+	vio_disable_interrupts(to_vio_dev(hostdata->dev));
+	tasklet_schedule(&hostdata->srp_task);
+	return IRQ_HANDLED;
+}
+
+/**
+ * release_crq_queue: - Deallocates data and unregisters CRQ
+ * @queue:	crq_queue to initialize and register
+ * @host_data:	ibmvscsi_host_data of host
+ *
+ * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
+ * the crq with the hypervisor.
+ */
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+				struct ibmvscsi_host_data *hostdata,
+				int max_requests)
+{
+	long rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+	free_irq(vdev->irq, (void *)hostdata);
+	tasklet_kill(&hostdata->srp_task);
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+	dma_unmap_single(hostdata->dev,
+			 queue->msg_token,
+			 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
+	free_page((unsigned long)queue->msgs);
+}
+
+/**
+ * crq_queue_next_crq: - Returns the next entry in message queue
+ * @queue:	crq_queue to use
+ *
+ * Returns pointer to next entry in queue, or NULL if there are no new 
+ * entried in the CRQ.
+ */
+static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
+{
+	struct viosrp_crq *crq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&queue->lock, flags);
+	crq = &queue->msgs[queue->cur];
+	if (crq->valid & 0x80) {
+		if (++queue->cur == queue->size)
+			queue->cur = 0;
+	} else
+		crq = NULL;
+	spin_unlock_irqrestore(&queue->lock, flags);
+
+	return crq;
+}
+
+/**
+ * ibmvscsi_send_crq: - Send a CRQ
+ * @hostdata:	the adapter
+ * @word1:	the first 64 bits of the data
+ * @word2:	the second 64 bits of the data
+ */
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+{
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
+}
+
+/**
+ * ibmvscsi_task: - Process srps asynchronously
+ * @data:	ibmvscsi_host_data of host
+ */
+static void ibmvscsi_task(void *data)
+{
+	struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+	struct viosrp_crq *crq;
+	int done = 0;
+
+	while (!done) {
+		/* Pull all the valid messages off the CRQ */
+		while ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
+			ibmvscsi_handle_crq(crq, hostdata);
+			crq->valid = 0x00;
+		}
+
+		vio_enable_interrupts(vdev);
+		if ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
+			vio_disable_interrupts(vdev);
+			ibmvscsi_handle_crq(crq, hostdata);
+			crq->valid = 0x00;
+		} else {
+			done = 1;
+		}
+	}
+}
+
+/**
+ * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ * Allocates a page for messages, maps it for dma, and registers
+ * the crq with the hypervisor.
+ * Returns zero on success.
+ */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+			    struct ibmvscsi_host_data *hostdata,
+			    int max_requests)
+{
+	int rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	queue->msgs = (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL);
+
+	if (!queue->msgs)
+		goto malloc_failed;
+	queue->size = PAGE_SIZE / sizeof(*queue->msgs);
+
+	queue->msg_token = dma_map_single(hostdata->dev, queue->msgs,
+					  queue->size * sizeof(*queue->msgs),
+					  DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(queue->msg_token))
+		goto map_failed;
+
+	rc = plpar_hcall_norets(H_REG_CRQ,
+				vdev->unit_address,
+				queue->msg_token, PAGE_SIZE);
+	if (rc == 2) {
+		/* Adapter is good, but other end is not ready */
+		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+	} else if (rc != 0) {
+		printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
+		goto reg_crq_failed;
+	}
+
+	if (request_irq(vdev->irq,
+			ibmvscsi_handle_event,
+			0, "ibmvscsi", (void *)hostdata) != 0) {
+		printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
+		       vdev->irq);
+		goto req_irq_failed;
+	}
+
+	rc = vio_enable_interrupts(vdev);
+	if (rc != 0) {
+		printk(KERN_ERR "ibmvscsi:  Error %d enabling interrupts!!!\n",
+		       rc);
+		goto req_irq_failed;
+	}
+
+	queue->cur = 0;
+	queue->lock = SPIN_LOCK_UNLOCKED;
+
+	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+		     (unsigned long)hostdata);
+
+	return 0;
+
+      req_irq_failed:
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+      reg_crq_failed:
+	dma_unmap_single(hostdata->dev,
+			 queue->msg_token,
+			 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
+      map_failed:
+	free_page((unsigned long)queue->msgs);
+      malloc_failed:
+	return -1;
+}
+
+/**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ */
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata)
+{
+	int rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	/* Close the CRQ */
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+
+	/* Clean out the queue */
+	memset(queue->msgs, 0x00, PAGE_SIZE);
+	queue->cur = 0;
+
+	/* And re-open it again */
+	rc = plpar_hcall_norets(H_REG_CRQ,
+				vdev->unit_address,
+				queue->msg_token, PAGE_SIZE);
+	if (rc == 2) {
+		/* Adapter is good, but other end is not ready */
+		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+	} else if (rc != 0) {
+		printk(KERN_WARNING
+		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
+	}
+}
diff -Nru a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/srp.h	2004-07-16 15:50:36 -07:00
@@ -0,0 +1,225 @@
+/*****************************************************************************/
+/* srp.h -- SCSI RDMA Protocol definitions                                   */
+/*                                                                           */
+/* Written By: Colin Devilbis, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 2003 IBM Corporation                                        */
+/*                                                                           */
+/* 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/*                                                                           */
+/* This file contains structures and definitions for the SCSI RDMA Protocol  */
+/* (SRP) as defined in the T10 standard available at www.t10.org.  This      */
+/* file was based on the 16a version of the standard                         */
+/*                                                                           */
+/*****************************************************************************/
+#ifndef SRP_H
+#define SRP_H
+
+#define PACKED __attribute__((packed))
+
+enum srp_types {
+	SRP_LOGIN_REQ_TYPE = 0x00,
+	SRP_LOGIN_RSP_TYPE = 0xC0,
+	SRP_LOGIN_REJ_TYPE = 0x80,
+	SRP_I_LOGOUT_TYPE = 0x03,
+	SRP_T_LOGOUT_TYPE = 0x80,
+	SRP_TSK_MGMT_TYPE = 0x01,
+	SRP_CMD_TYPE = 0x02,
+	SRP_RSP_TYPE = 0xC1,
+	SRP_CRED_REQ_TYPE = 0x81,
+	SRP_CRED_RSP_TYPE = 0x41,
+	SRP_AER_REQ_TYPE = 0x82,
+	SRP_AER_RSP_TYPE = 0x42
+};
+
+enum srp_descriptor_formats {
+	SRP_NO_BUFFER = 0x00,
+	SRP_DIRECT_BUFFER = 0x01,
+	SRP_INDIRECT_BUFFER = 0x02
+};
+
+struct memory_descriptor {
+	u64 virtual_address;
+	u32 memory_handle;
+	u32 length;
+};
+
+struct indirect_descriptor {
+	struct memory_descriptor head;
+	u32 total_length;
+	struct memory_descriptor list[1] PACKED;
+};
+
+struct srp_generic {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+};
+
+struct srp_login_req {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+	u32 max_requested_initiator_to_target_iulen;
+	u32 reserved2;
+	u16 required_buffer_formats;
+	u8 reserved3:6;
+	u8 multi_channel_action:2;
+	u8 reserved4;
+	u32 reserved5;
+	u8 initiator_port_identifier[16];
+	u8 target_port_identifier[16];
+};
+
+struct srp_login_rsp {
+	u8 type;
+	u8 reserved1[3];
+	u32 request_limit_delta;
+	u64 tag;
+	u32 max_initiator_to_target_iulen;
+	u32 max_target_to_initiator_iulen;
+	u16 supported_buffer_formats;
+	u8 reserved2:6;
+	u8 multi_channel_result:2;
+	u8 reserved3;
+	u8 reserved4[24];
+};
+
+struct srp_login_rej {
+	u8 type;
+	u8 reserved1[3];
+	u32 reason;
+	u64 tag;
+	u64 reserved2;
+	u16 supported_buffer_formats;
+	u8 reserved3[6];
+};
+
+struct srp_i_logout {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+};
+
+struct srp_t_logout {
+	u8 type;
+	u8 reserved1[3];
+	u32 reason;
+	u64 tag;
+};
+
+struct srp_tsk_mgmt {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+	u32 reserved2;
+	u64 lun PACKED;
+	u8 reserved3;
+	u8 reserved4;
+	u8 task_mgmt_flags;
+	u8 reserved5;
+	u64 managed_task_tag;
+	u64 reserved6;
+};
+
+struct srp_cmd {
+	u8 type;
+	u32 reserved1 PACKED;
+	u8 data_out_format:4;
+	u8 data_in_format:4;
+	u8 data_out_count;
+	u8 data_in_count;
+	u64 tag;
+	u32 reserved2;
+	u64 lun PACKED;
+	u8 reserved3;
+	u8 reserved4:5;
+	u8 task_attribute:3;
+	u8 reserved5;
+	u8 additional_cdb_len;
+	u8 cdb[16];
+	u8 additional_data[0x100 - 0x30];
+};
+
+struct srp_rsp {
+	u8 type;
+	u8 reserved1[3];
+	u32 request_limit_delta;
+	u64 tag;
+	u16 reserved2;
+	u8 reserved3:2;
+	u8 diunder:1;
+	u8 diover:1;
+	u8 dounder:1;
+	u8 doover:1;
+	u8 snsvalid:1;
+	u8 rspvalid:1;
+	u8 status;
+	u32 data_in_residual_count;
+	u32 data_out_residual_count;
+	u32 sense_data_list_length;
+	u32 response_data_list_length;
+	u8 sense_and_response_data[18];
+};
+
+struct srp_cred_req {
+	u8 type;
+	u8 reserved1[3];
+	u32 request_limit_delta;
+	u64 tag;
+};
+
+struct srp_cred_rsp {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+};
+
+struct srp_aer_req {
+	u8 type;
+	u8 reserved1[3];
+	u32 request_limit_delta;
+	u64 tag;
+	u32 reserved2;
+	u64 lun;
+	u32 sense_data_list_length;
+	u32 reserved3;
+	u8 sense_data[20];
+};
+
+struct srp_aer_rsp {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+};
+
+union srp_iu {
+	struct srp_generic generic;
+	struct srp_login_req login_req;
+	struct srp_login_rsp login_rsp;
+	struct srp_login_rej login_rej;
+	struct srp_i_logout i_logout;
+	struct srp_t_logout t_logout;
+	struct srp_tsk_mgmt tsk_mgmt;
+	struct srp_cmd cmd;
+	struct srp_rsp rsp;
+	struct srp_cred_req cred_req;
+	struct srp_cred_rsp cred_rsp;
+	struct srp_aer_req aer_req;
+	struct srp_aer_rsp aer_rsp;
+};
+
+#endif
diff -Nru a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/viosrp.h	2004-07-16 15:50:36 -07:00
@@ -0,0 +1,126 @@
+/*****************************************************************************/
+/* srp.h -- SCSI RDMA Protocol definitions                                   */
+/*                                                                           */
+/* Written By: Colin Devilbis, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 2003 IBM Corporation                                        */
+/*                                                                           */
+/* 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/*                                                                           */
+/* This file contains structures and definitions for IBM RPA (RS/6000        */
+/* platform architecture) implementation of the SRP (SCSI RDMA Protocol)     */
+/* standard.  SRP is used on IBM iSeries and pSeries platforms to send SCSI  */
+/* commands between logical partitions.                                      */
+/*                                                                           */
+/* SRP Information Units (IUs) are sent on a "Command/Response Queue" (CRQ)  */
+/* between partitions.  The definitions in this file are architected,        */
+/* and cannot be changed without breaking compatibility with other versions  */
+/* of Linux and other operating systems (AIX, OS/400) that talk this protocol*/
+/* between logical partitions                                                */
+/*****************************************************************************/
+#ifndef VIOSRP_H
+#define VIOSRP_H
+#include "srp.h"
+
+enum viosrp_crq_formats {
+	VIOSRP_SRP_FORMAT = 0x01,
+	VIOSRP_MAD_FORMAT = 0x02,
+	VIOSRP_OS400_FORMAT = 0x03,
+	VIOSRP_AIX_FORMAT = 0x04,
+	VIOSRP_LINUX_FORMAT = 0x06,
+	VIOSRP_INLINE_FORMAT = 0x07
+};
+
+struct viosrp_crq {
+	u8 valid;		/* used by RPA */
+	u8 format;		/* SCSI vs out-of-band */
+	u8 reserved;
+	u8 status;		/* non-scsi failure? (e.g. DMA failure) */
+	u16 timeout;		/* in seconds */
+	u16 IU_length;		/* in bytes */
+	u64 IU_data_ptr;	/* the TCE for transferring data */
+};
+
+/* MADs are Management requests above and beyond the IUs defined in the SRP
+ * standard.  
+ */
+enum viosrp_mad_types {
+	VIOSRP_EMPTY_IU_TYPE = 0x01,
+	VIOSRP_ERROR_LOG_TYPE = 0x02,
+	VIOSRP_ADAPTER_INFO_TYPE = 0x03,
+	VIOSRP_HOST_CONFIG_TYPE = 0x04
+};
+
+/* 
+ * Common MAD header
+ */
+struct mad_common {
+	u32 type;
+	u16 status;
+	u16 length;
+	u64 tag;
+};
+
+/*
+ * All SRP (and MAD) requests normally flow from the
+ * client to the server.  There is no way for the server to send
+ * an asynchronous message back to the client.  The Empty IU is used
+ * to hang out a meaningless request to the server so that it can respond
+ * asynchrouously with something like a SCSI AER 
+ */
+struct viosrp_empty_iu {
+	struct mad_common common;
+	u64 buffer;
+	u32 port;
+};
+
+struct viosrp_error_log {
+	struct mad_common common;
+	u64 buffer;
+};
+
+struct viosrp_adapter_info {
+	struct mad_common common;
+	u64 buffer;
+};
+
+struct viosrp_host_config {
+	struct mad_common common;
+	u64 buffer;
+};
+
+union mad_iu {
+	struct viosrp_empty_iu empty_iu;
+	struct viosrp_error_log error_log;
+	struct viosrp_adapter_info adapter_info;
+	struct viosrp_host_config host_config;
+};
+
+union viosrp_iu {
+	union srp_iu srp;
+	union mad_iu mad;
+};
+
+struct mad_adapter_info_data {
+	char srp_version[8];
+	char partition_name[96];
+	u32 partition_number;
+	u32 mad_version;
+	u32 os_type;
+	u32 port_max_txu[8];	/* per-port maximum transfer */
+};
+
+#endif
diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c
--- a/drivers/scsi/imm.c	2004-08-04 07:56:45 -07:00
+++ b/drivers/scsi/imm.c	2004-08-24 16:09:03 -07:00
@@ -758,7 +758,7 @@
 	case DID_OK:
 		break;
 	case DID_NO_CONNECT:
-		printk("imm: no device at SCSI ID %i\n", cmd->target);
+		printk("imm: no device at SCSI ID %i\n", cmd->device->id);
 		break;
 	case DID_BUS_BUSY:
 		printk("imm: BUS BUSY - EPP timeout detected\n");
diff -Nru a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
--- a/drivers/scsi/ipr.c	2004-06-07 15:11:05 -07:00
+++ b/drivers/scsi/ipr.c	2004-08-15 23:40:17 -07:00
@@ -1,7 +1,7 @@
 /*
  * ipr.c -- driver for IBM Power Linux RAID adapters
  *
- * Written By: Brian King, IBM Corporation
+ * Written By: Brian King <brking@us.ibm.com>, IBM Corporation
  *
  * Copyright (C) 2003, 2004 IBM Corporation
  *
@@ -93,7 +93,7 @@
 
 /* This table describes the differences between DMA controller chips */
 static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
-	{ /* Gemstone */
+	{ /* Gemstone and Citrine */
 		.mailbox = 0x0042C,
 		.cache_line_size = 0x20,
 		{
@@ -208,6 +208,8 @@
 	"Synchronization required"},
 	{0x024E0000, 0, 0,
 	"No ready, IOA shutdown"},
+	{0x025A0000, 0, 0,
+	"Not ready, IOA has been shutdown"},
 	{0x02670100, 0, 1,
 	"3020: Storage subsystem configuration error"},
 	{0x03110B00, 0, 0,
@@ -880,11 +882,13 @@
  **/
 static void ipr_log_vpd(struct ipr_std_inq_vpids *vpids, u8 *serial_num)
 {
-	char buffer[max_t(int, sizeof(struct ipr_std_inq_vpids),
-			  IPR_SERIAL_NUM_LEN) + 1];
+	char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN
+		    + IPR_SERIAL_NUM_LEN];
 
-	memcpy(buffer, vpids, sizeof(struct ipr_std_inq_vpids));
-	buffer[sizeof(struct ipr_std_inq_vpids)] = '\0';
+	memcpy(buffer, vpids->vendor_id, IPR_VENDOR_ID_LEN);
+	memcpy(buffer + IPR_VENDOR_ID_LEN, vpids->product_id,
+	       IPR_PROD_ID_LEN);
+	buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN] = '\0';
 	ipr_err("Vendor/Product ID: %s\n", buffer);
 
 	memcpy(buffer, serial_num, IPR_SERIAL_NUM_LEN);
@@ -1766,6 +1770,33 @@
 #endif
 
 /**
+ * ipr_release_dump - Free adapter dump memory
+ * @kref:	kref struct
+ *
+ * Return value:
+ *	nothing
+ **/
+static void ipr_release_dump(struct kref *kref)
+{
+	struct ipr_dump *dump = container_of(kref,struct ipr_dump,kref);
+	struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg;
+	unsigned long lock_flags = 0;
+	int i;
+
+	ENTER;
+	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+	ioa_cfg->dump = NULL;
+	ioa_cfg->sdt_state = INACTIVE;
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+
+	for (i = 0; i < dump->ioa_dump.next_page_index; i++)
+		free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
+
+	kfree(dump);
+	LEAVE;
+}
+
+/**
  * ipr_worker_thread - Worker thread
  * @data:		ioa config struct
  *
@@ -1791,13 +1822,13 @@
 
 	if (ioa_cfg->sdt_state == GET_DUMP) {
 		dump = ioa_cfg->dump;
-		if (!dump || !kobject_get(&dump->kobj)) {
+		if (!dump || !kref_get(&dump->kref)) {
 			spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 			return;
 		}
 		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 		ipr_get_ioa_dump(ioa_cfg, dump);
-		kobject_put(&dump->kobj);
+		kref_put(&dump->kref, ipr_release_dump);
 
 		spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 		if (ioa_cfg->sdt_state == DUMP_OBTAINED)
@@ -2008,7 +2039,7 @@
 		wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
 
 		/* Wait for a second for any errors to be logged */
-		schedule_timeout(HZ);
+		msleep(1000);
 	} else {
 		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 		return -EIO;
@@ -2392,7 +2423,7 @@
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 	dump = ioa_cfg->dump;
 
-	if (ioa_cfg->sdt_state != DUMP_OBTAINED || !dump || !kobject_get(&dump->kobj)) {
+	if (ioa_cfg->sdt_state != DUMP_OBTAINED || !dump || !kref_get(&dump->kref)) {
 		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 		return 0;
 	}
@@ -2400,7 +2431,7 @@
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
 	if (off > dump->driver_dump.hdr.len) {
-		kobject_put(&dump->kobj);
+		kref_put(&dump->kref, ipr_release_dump);
 		return 0;
 	}
 
@@ -2450,42 +2481,11 @@
 		count -= len;
 	}
 
-	kobject_put(&dump->kobj);
+	kref_put(&dump->kref, ipr_release_dump);
 	return rc;
 }
 
 /**
- * ipr_release_dump - Free adapter dump memory
- * @kobj:	kobject struct
- *
- * Return value:
- *	nothing
- **/
-static void ipr_release_dump(struct kobject *kobj)
-{
-	struct ipr_dump *dump = container_of(kobj,struct ipr_dump,kobj);
-	struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg;
-	unsigned long lock_flags = 0;
-	int i;
-
-	ENTER;
-	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
-	ioa_cfg->dump = NULL;
-	ioa_cfg->sdt_state = INACTIVE;
-	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-
-	for (i = 0; i < dump->ioa_dump.next_page_index; i++)
-		free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
-
-	kfree(dump);
-	LEAVE;
-}
-
-static struct kobj_type ipr_dump_kobj_type = {
-	.release = ipr_release_dump,
-};
-
-/**
  * ipr_alloc_dump - Prepare for adapter dump
  * @ioa_cfg:	ioa config struct
  *
@@ -2506,8 +2506,7 @@
 	}
 
 	memset(dump, 0, sizeof(struct ipr_dump));
-	kobject_init(&dump->kobj);
-	dump->kobj.ktype = &ipr_dump_kobj_type;
+	kref_init(&dump->kref);
 	dump->ioa_cfg = ioa_cfg;
 
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -2554,7 +2553,7 @@
 	ioa_cfg->dump = NULL;
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
-	kobject_put(&dump->kobj);
+	kref_put(&dump->kref, ipr_release_dump);
 
 	LEAVE;
 	return 0;
@@ -2690,8 +2689,6 @@
 	struct ipr_resource_entry *res;
 	unsigned long lock_flags = 0;
 	int tcq_active = simple_strtoul(buf, NULL, 10);
-	int qdepth = IPR_MAX_CMD_PER_LUN;
-	int tagged = 0;
 	ssize_t len = -ENXIO;
 
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -2699,13 +2696,13 @@
 	res = (struct ipr_resource_entry *)sdev->hostdata;
 
 	if (res) {
-		res->tcq_active = 0;
-		qdepth = res->qdepth;
-
 		if (ipr_is_gscsi(res) && sdev->tagged_supported) {
 			if (tcq_active) {
-				tagged = MSG_ORDERED_TAG;
 				res->tcq_active = 1;
+				scsi_activate_tcq(sdev, res->qdepth);
+			} else {
+				res->tcq_active = 0;
+				scsi_deactivate_tcq(sdev, res->qdepth);
 			}
 
 			len = strlen(buf);
@@ -2715,7 +2712,6 @@
 	}
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-	scsi_adjust_queue_depth(sdev, tagged, qdepth);
 	return len;
 }
 
@@ -2785,7 +2781,8 @@
 			 struct block_device *block_device,
 			 sector_t capacity, int *parm)
 {
-	int heads, sectors, cylinders;
+	int heads, sectors;
+	sector_t cylinders;
 
 	heads = 128;
 	sectors = 32;
@@ -2849,8 +2846,8 @@
 			sdev->scsi_level = 4;
 		if (ipr_is_vset_device(res))
 			sdev->timeout = IPR_VSET_RW_TIMEOUT;
-
-		sdev->allow_restart = 1;
+		if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+			sdev->allow_restart = 1;
 		scsi_adjust_queue_depth(sdev, 0, res->qdepth);
 	}
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -3080,7 +3077,7 @@
 	struct ipr_ioa_cfg *ioa_cfg;
 	struct ipr_resource_entry *res;
 	struct ipr_cmd_pkt *cmd_pkt;
-	u32 ioasc, ioarcb_addr;
+	u32 ioasc;
 	int op_found = 0;
 
 	ENTER;
@@ -3101,21 +3098,15 @@
 	if (!op_found)
 		return SUCCESS;
 
-	ioarcb_addr = be32_to_cpu(ipr_cmd->ioarcb.ioarcb_host_pci_addr);
-
 	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle;
 	cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
 	cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
-	cmd_pkt->cdb[0] = IPR_ABORT_TASK;
-	cmd_pkt->cdb[2] = (ioarcb_addr >> 24) & 0xff;
-	cmd_pkt->cdb[3] = (ioarcb_addr >> 16) & 0xff;
-	cmd_pkt->cdb[4] = (ioarcb_addr >> 8) & 0xff;
-	cmd_pkt->cdb[5] = ioarcb_addr & 0xff;
+	cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS;
 	ipr_cmd->u.sdev = scsi_cmd->device;
 
 	ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]);
-	ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_ABORT_TASK_TIMEOUT);
+	ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
 	ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 
 	/*
@@ -3737,7 +3728,7 @@
 
 	switch (ioasc & IPR_IOASC_IOASC_MASK) {
 	case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
-		scsi_cmd->result |= (DID_ERROR << 16);
+		scsi_cmd->result |= (DID_IMM_RETRY << 16);
 		break;
 	case IPR_IOASC_IR_RESOURCE_HANDLE:
 		scsi_cmd->result |= (DID_NO_CONNECT << 16);
@@ -3873,7 +3864,7 @@
 	 * We have told the host to stop giving us new requests, but
 	 * ERP ops don't count. FIXME
 	 */
-	if (unlikely(!ioa_cfg->allow_cmds))
+	if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead))
 		return SCSI_MLQUEUE_HOST_BUSY;
 
 	/*
@@ -5437,13 +5428,15 @@
  **/
 static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
 {
+	struct pci_dev *pdev = ioa_cfg->pdev;
+
 	ENTER;
-	free_irq(ioa_cfg->pdev->irq, ioa_cfg);
+	free_irq(pdev->irq, ioa_cfg);
 	iounmap((void *) ioa_cfg->hdw_dma_regs);
-	release_mem_region(ioa_cfg->hdw_dma_regs_pci,
-			   pci_resource_len(ioa_cfg->pdev, 0));
+	pci_release_regions(pdev);
 	ipr_free_mem(ioa_cfg);
 	scsi_host_put(ioa_cfg->host);
+	pci_disable_device(pdev);
 	LEAVE;
 }
 
@@ -5458,7 +5451,7 @@
 {
 	struct ipr_cmnd *ipr_cmd;
 	struct ipr_ioarcb *ioarcb;
-	u32 dma_addr;
+	dma_addr_t dma_addr;
 	int i;
 
 	ioa_cfg->ipr_cmd_pool = pci_pool_create (IPR_NAME, ioa_cfg->pdev,
@@ -5508,14 +5501,15 @@
  **/
 static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
 {
-	int i;
+	struct pci_dev *pdev = ioa_cfg->pdev;
+	int i, rc = -ENOMEM;
 
 	ENTER;
 	ioa_cfg->res_entries = kmalloc(sizeof(struct ipr_resource_entry) *
 				       IPR_MAX_PHYSICAL_DEVS, GFP_KERNEL);
 
 	if (!ioa_cfg->res_entries)
-		goto cleanup;
+		goto out;
 
 	memset(ioa_cfg->res_entries, 0,
 	       sizeof(struct ipr_resource_entry) * IPR_MAX_PHYSICAL_DEVS);
@@ -5528,24 +5522,24 @@
 						&ioa_cfg->vpd_cbs_dma);
 
 	if (!ioa_cfg->vpd_cbs)
-		goto cleanup;
+		goto out_free_res_entries;
 
 	if (ipr_alloc_cmd_blks(ioa_cfg))
-		goto cleanup;
+		goto out_free_vpd_cbs;
 
 	ioa_cfg->host_rrq = pci_alloc_consistent(ioa_cfg->pdev,
 						 sizeof(u32) * IPR_NUM_CMD_BLKS,
 						 &ioa_cfg->host_rrq_dma);
 
 	if (!ioa_cfg->host_rrq)
-		goto cleanup;
+		goto out_ipr_free_cmd_blocks;
 
 	ioa_cfg->cfg_table = pci_alloc_consistent(ioa_cfg->pdev,
 						  sizeof(struct ipr_config_table),
 						  &ioa_cfg->cfg_table_dma);
 
 	if (!ioa_cfg->cfg_table)
-		goto cleanup;
+		goto out_free_host_rrq;
 
 	for (i = 0; i < IPR_NUM_HCAMS; i++) {
 		ioa_cfg->hostrcb[i] = pci_alloc_consistent(ioa_cfg->pdev,
@@ -5553,9 +5547,8 @@
 							   &ioa_cfg->hostrcb_dma[i]);
 
 		if (!ioa_cfg->hostrcb[i])
-			goto cleanup;
+			goto out_free_hostrcb_dma;
 
-		memset(ioa_cfg->hostrcb[i], 0, sizeof(struct ipr_hostrcb));
 		ioa_cfg->hostrcb[i]->hostrcb_dma =
 			ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam);
 		list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q);
@@ -5565,19 +5558,35 @@
 				 IPR_NUM_TRACE_ENTRIES, GFP_KERNEL);
 
 	if (!ioa_cfg->trace)
-		goto cleanup;
+		goto out_free_hostrcb_dma;
 
 	memset(ioa_cfg->trace, 0,
 	       sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES);
 
+	rc = 0;
+out:
 	LEAVE;
-	return 0;
-
-cleanup:
-	ipr_free_mem(ioa_cfg);
+	return rc;
 
-	LEAVE;
-	return -ENOMEM;
+out_free_hostrcb_dma:
+	while (i-- > 0) {
+		pci_free_consistent(pdev, sizeof(struct ipr_hostrcb),
+				    ioa_cfg->hostrcb[i],
+				    ioa_cfg->hostrcb_dma[i]);
+	}
+	pci_free_consistent(pdev, sizeof(struct ipr_config_table),
+			    ioa_cfg->cfg_table, ioa_cfg->cfg_table_dma);
+out_free_host_rrq:
+	pci_free_consistent(pdev, sizeof(u32) * IPR_NUM_CMD_BLKS,
+			    ioa_cfg->host_rrq, ioa_cfg->host_rrq_dma);
+out_ipr_free_cmd_blocks:
+	ipr_free_cmd_blks(ioa_cfg);
+out_free_vpd_cbs:
+	pci_free_consistent(pdev, sizeof(struct ipr_misc_cbs),
+			    ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
+out_free_res_entries:
+	kfree(ioa_cfg->res_entries);
+	goto out;
 }
 
 /**
@@ -5678,7 +5687,7 @@
 
 	if ((rc = pci_enable_device(pdev))) {
 		dev_err(&pdev->dev, "Cannot enable adapter\n");
-		return rc;
+		goto out;
 	}
 
 	dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq);
@@ -5687,7 +5696,8 @@
 
 	if (!host) {
 		dev_err(&pdev->dev, "call to scsi_host_alloc failed!\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_disable;
 	}
 
 	ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata;
@@ -5697,12 +5707,11 @@
 
 	ipr_regs_pci = pci_resource_start(pdev, 0);
 
-	if (!request_mem_region(ipr_regs_pci,
-				pci_resource_len(pdev, 0), IPR_NAME)) {
+	rc = pci_request_regions(pdev, IPR_NAME);
+	if (rc < 0) {
 		dev_err(&pdev->dev,
 			"Couldn't register memory range of registers\n");
-		scsi_host_put(host);
-		return -ENOMEM;
+		goto out_scsi_host_put;
 	}
 
 	ipr_regs = (unsigned long)ioremap(ipr_regs_pci,
@@ -5711,9 +5720,8 @@
 	if (!ipr_regs) {
 		dev_err(&pdev->dev,
 			"Couldn't map memory range of registers\n");
-		release_mem_region(ipr_regs_pci, pci_resource_len(pdev, 0));
-		scsi_host_put(host);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_release_regions;
 	}
 
 	ioa_cfg->hdw_dma_regs = ipr_regs;
@@ -5723,11 +5731,10 @@
 	ipr_init_ioa_cfg(ioa_cfg, host, pdev);
 
 	pci_set_master(pdev);
-	rc = pci_set_dma_mask(pdev, 0xffffffff);
 
-	if (rc != PCIBIOS_SUCCESSFUL) {
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc < 0) {
 		dev_err(&pdev->dev, "Failed to set PCI DMA mask\n");
-		rc = -EIO;
 		goto cleanup_nomem;
 	}
 
@@ -5755,8 +5762,12 @@
 	if ((rc = ipr_set_pcix_cmd_reg(ioa_cfg)))
 		goto cleanup_nomem;
 
-	if ((rc = ipr_alloc_mem(ioa_cfg)))
-		goto cleanup;
+	rc = ipr_alloc_mem(ioa_cfg);
+	if (rc < 0) {
+		dev_err(&pdev->dev,
+			"Couldn't allocate enough memory for device driver!\n");
+		goto cleanup_nomem;
+	}
 
 	ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
 	rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg);
@@ -5772,18 +5783,20 @@
 	spin_unlock(&ipr_driver_lock);
 
 	LEAVE;
-	return 0;
+out:
+	return rc;
 
-cleanup:
-	dev_err(&pdev->dev, "Couldn't allocate enough memory for device driver!\n");
 cleanup_nolog:
 	ipr_free_mem(ioa_cfg);
 cleanup_nomem:
 	iounmap((void *) ipr_regs);
-	release_mem_region(ipr_regs_pci, pci_resource_len(pdev, 0));
+out_release_regions:
+	pci_release_regions(pdev);
+out_scsi_host_put:
 	scsi_host_put(host);
-
-	return rc;
+out_disable:
+	pci_disable_device(pdev);
+	goto out;
 }
 
 /**
@@ -5988,9 +6001,15 @@
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
 		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D,
 	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B,
+	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
 		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780,
 		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_p:
-	delpma[i]);
+	}
+	pci_free_consistent(NIPE,
/
 static void ipr_l6dev_eOR_cHle= {
-	, eturn -E sllocates a p_carc;
+E, ioa_cfg->pdfg = a_cfgEVICE_+	u4dev[Wip_cfurd 	);
 t) {
 		dev_err(&pdev-      *g lock-Adev,
+_regi 	);
532 dma_ remap,ev, 0));
+out_release_re1I_VENDOR_ID_IBM, P));ED_IECTIONAL);
+      map_3pr_isrs, ioa_d
-	return 0;
+out:
+	rrelease_regions:
+NIPE,
/
 static void ipr_l6dev_eWip_devinit ipr_alloc_mem{
 		dev_err(&pdev-      *g loEV_ID_5struct2scp.h	200R*g loEV_ {
  dma
 		devuuEregs_pci = pci_resource_start(pdev, 0);
 
-	if (!request_m;
 a
 			spiCPif (ioRigned Tre1I_VENDOR_ID_IBM, P));ED  (AIX, OS/40
@@ -24 __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
 {
2&regs_pc/ibmvslpr_u	t@@ -3080,7 +3077,e_hosags);
 	dump = ioa_cfg->dump;
 
-	i77,e_hosags);
 	d_SERIArpervisor.
+ */
+void ibmvsceA2,
+a )[>sAcfurdigned T */
+void ibtic void ipr_lB    NS_DEV_ID_278"NoO3728,7 @@imeoutpter du1eA2)ic void goto -3080,7 + @@imutpter du1eA2)ic voDOR_D6900
+++ b/drivers/_pkt ic 2 data_ble_device(pdev);
+	goto out;
 }
 
 /**
@@ -5988,9 +GbIOA with IRQ: %d\n", pOMEMailed to set PCI 6E5SsOA with IRQ:eof(tur8
 	if (!op_found)
 		return SUCCESS;
 
-	ioarcb_addr = be32_to_cpu_IBM_CITRI@ -24 _rcb_addr = be32_ip_cfg[0]ueSipr_regs0]ueS}tag;
uem(ioa_c32_ip_rrq)
-		goto d6;
+};
+
+strt pci_resoT *L2 0, 0,
d to s_cfg->pdev,
 oT *L2 0,dlin_unlock(&ipr_drivimeoutpED  (AIX, O		return rc;
+		got 0, M_p:
-	Rav,
 oT 
/
 s  loEV_ID_5struct2scp.h	200R*g loEV_ {
  dma
 		devuuEregs_pci = pci_resource_start(p ---M_CITRI@ -rved1[3];
;+5501,ev_err; i++) 6_unl-rved1[3];
;+5ioa_cfg->cfg_table_dma);
 
 	iQ:eof(tur8
 	if g3];
;+550i fd(Epin_unlock_irqrestore(ioa_cfg->h, @@
  *Tpg->cf	returndevruct sregioni_d0));
-af	rels.   ));
+out_releasesgioni_d0));
-aT 
/
 s  loEV_ID_5struct2scp.h	21,e.
@@ -5755,8 +    
/cmds && !it cylinders;
 
 	he n len TCE:_ID_ME, ioa_cfg->pdev,

/
1t i;
+
+	E)ia
 		dev=TCE+5501,ev_err; i++) 6_unl-rved1[3];
;+5ioa_cfg->cfg_table_dma)l	8 +    
/cmds && !it cylist pn");
+ev = to_vio_dev(ho _ES);
 
+	rc = 0;
+out:
 	Lg& !it cylist pvedogramBM, P));ED  (AIX, OS/istent(ble_dma"P));uoreserved+& sdev->t2
 	}v,
 oT 
/
 s(ioa_c5CE+5501,evid ibtic void ipr_lB    NS_DEV_ID_278"NoO3728,7 @@ime   *L2 0iS d6;
+};
+
+strt pci_resoT q);
@@ -55;		if (I                       Acfu)
 {
2&regs_pc/ib;